From 7b2c90ca7581f67d5a8fb74c25076f08cfb16cb2 Mon Sep 17 00:00:00 2001 From: triniwiz Date: Thu, 3 Jun 2021 18:21:38 -0400 Subject: [PATCH 01/11] init --- .gitignore | 6 ++++ Cargo.toml | 12 ++++++++ TestApp/TestApp.sln | 25 ++++++++++++++++ TestApp/TestApp/App/main.js | 7 +++++ TestApp/TestApp/Program.cs | 29 +++++++++++++++++++ .../TestApp/Properties/launchSettings.json | 8 +++++ TestApp/TestApp/TestApp.csproj | 21 ++++++++++++++ 7 files changed, 108 insertions(+) create mode 100644 .gitignore create mode 100755 Cargo.toml create mode 100755 TestApp/TestApp.sln create mode 100755 TestApp/TestApp/App/main.js create mode 100755 TestApp/TestApp/Program.cs create mode 100755 TestApp/TestApp/Properties/launchSettings.json create mode 100755 TestApp/TestApp/TestApp.csproj diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..519caa8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ + +/target +/**/*.rs.bk +/Cargo.lock +.DS_Store +.vs \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100755 index 0000000..30cf9b6 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[workspace] + +members = ["core"] + +[profile.release] +panic = "abort" +codegen-units = 1 +lto = true +#opt-level = 3 +opt-level = "z" +debug = false +incremental = false \ No newline at end of file diff --git a/TestApp/TestApp.sln b/TestApp/TestApp.sln new file mode 100755 index 0000000..91b6f5e --- /dev/null +++ b/TestApp/TestApp.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31321.278 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApp", "TestApp\TestApp.csproj", "{BF77710B-81A6-4F79-9608-B9D8A7C2DF55}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BF77710B-81A6-4F79-9608-B9D8A7C2DF55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BF77710B-81A6-4F79-9608-B9D8A7C2DF55}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BF77710B-81A6-4F79-9608-B9D8A7C2DF55}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BF77710B-81A6-4F79-9608-B9D8A7C2DF55}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D42E46BA-4BE0-4971-ADDF-4D22BFD6F2C8} + EndGlobalSection +EndGlobal diff --git a/TestApp/TestApp/App/main.js b/TestApp/TestApp/App/main.js new file mode 100755 index 0000000..98fb8fd --- /dev/null +++ b/TestApp/TestApp/App/main.js @@ -0,0 +1,7 @@ +console.log("me"); + +console.log(Date.now(), time(), performance.now()); + +const MessageDialog = $("Windows.UI.Popups.MessageDialog"); +const dialog = new MessageDialog("Hello, World!"); +dialog.ShowAsync(); \ No newline at end of file diff --git a/TestApp/TestApp/Program.cs b/TestApp/TestApp/Program.cs new file mode 100755 index 0000000..dda9bc3 --- /dev/null +++ b/TestApp/TestApp/Program.cs @@ -0,0 +1,29 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +namespace TestApp +{ + class Program + + { + + + + [DllImport("nativescript.dll")] + public static extern void hello(); + + [DllImport("nativescript.dll")] + public static extern Int64 runtime_init([MarshalAs(UnmanagedType.LPUTF8Str)] string entry); + + [DllImport("nativescript.dll")] + public static extern void runtime_runscript(Int64 runtime, [MarshalAs(UnmanagedType.LPUTF8Str)] string entry); + + static void Main(string[] args) + { + + string entry = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "App\\main.js"); + Int64 runtime = runtime_init(AppContext.BaseDirectory); + runtime_runscript(runtime, File.ReadAllText(Path.GetFullPath(entry))); + } + } +} diff --git a/TestApp/TestApp/Properties/launchSettings.json b/TestApp/TestApp/Properties/launchSettings.json new file mode 100755 index 0000000..ce70851 --- /dev/null +++ b/TestApp/TestApp/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "TestApp": { + "commandName": "Project", + "nativeDebugging": true + } + } +} \ No newline at end of file diff --git a/TestApp/TestApp/TestApp.csproj b/TestApp/TestApp/TestApp.csproj new file mode 100755 index 0000000..cc7892f --- /dev/null +++ b/TestApp/TestApp/TestApp.csproj @@ -0,0 +1,21 @@ + + + + Exe + net5.0 + + + + + Always + + + Always + + + + + + + + From 720df4b3fb1ae6b252811f99d4c9458c6f891091 Mon Sep 17 00:00:00 2001 From: triniwiz Date: Thu, 3 Jun 2021 18:22:33 -0400 Subject: [PATCH 02/11] feat: core --- core/.gitignore | 2 + core/.idea/.gitignore | 8 + core/.idea/core.iml | 8 + core/.idea/modules.xml | 8 + core/.idea/vcs.xml | 6 + core/Cargo.toml | 22 ++ core/bindings/Cargo.toml | 10 + core/bindings/build.rs | 10 + core/bindings/src/lib.rs | 1 + core/build.rs | 33 ++ core/src/bindings.cpp | 91 ++++++ core/src/bindings.rs | 60 ++++ core/src/headers.h | 10 + core/src/lib.rs | 9 + core/src/metadata/com_helpers.rs | 61 ++++ core/src/metadata/declarations/declaration.rs | 32 ++ .../metadata/declarations/enum_declaration.rs | 27 ++ .../declarations/field_declaration.rs | 66 ++++ core/src/metadata/declarations/mod.rs | 4 + .../metadata/declarations/type_declaration.rs | 79 +++++ core/src/metadata/mod.rs | 10 + core/src/metadata/token_type.rs | 64 ++++ core/src/prelude.rs | 32 ++ core/src/runtime/console.rs | 50 +++ core/src/runtime/ffi/mod.rs | 0 core/src/runtime/global.rs | 0 core/src/runtime/mod.rs | 305 ++++++++++++++++++ 27 files changed, 1008 insertions(+) create mode 100755 core/.gitignore create mode 100644 core/.idea/.gitignore create mode 100644 core/.idea/core.iml create mode 100644 core/.idea/modules.xml create mode 100644 core/.idea/vcs.xml create mode 100755 core/Cargo.toml create mode 100755 core/bindings/Cargo.toml create mode 100755 core/bindings/build.rs create mode 100755 core/bindings/src/lib.rs create mode 100755 core/build.rs create mode 100755 core/src/bindings.cpp create mode 100644 core/src/bindings.rs create mode 100755 core/src/headers.h create mode 100755 core/src/lib.rs create mode 100755 core/src/metadata/com_helpers.rs create mode 100644 core/src/metadata/declarations/declaration.rs create mode 100644 core/src/metadata/declarations/enum_declaration.rs create mode 100644 core/src/metadata/declarations/field_declaration.rs create mode 100644 core/src/metadata/declarations/mod.rs create mode 100644 core/src/metadata/declarations/type_declaration.rs create mode 100755 core/src/metadata/mod.rs create mode 100755 core/src/metadata/token_type.rs create mode 100644 core/src/prelude.rs create mode 100755 core/src/runtime/console.rs create mode 100755 core/src/runtime/ffi/mod.rs create mode 100755 core/src/runtime/global.rs create mode 100755 core/src/runtime/mod.rs diff --git a/core/.gitignore b/core/.gitignore new file mode 100755 index 0000000..96ef6c0 --- /dev/null +++ b/core/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/core/.idea/.gitignore b/core/.idea/.gitignore new file mode 100644 index 0000000..73f69e0 --- /dev/null +++ b/core/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/core/.idea/core.iml b/core/.idea/core.iml new file mode 100644 index 0000000..bc2cd87 --- /dev/null +++ b/core/.idea/core.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/core/.idea/modules.xml b/core/.idea/modules.xml new file mode 100644 index 0000000..402ffa7 --- /dev/null +++ b/core/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/core/.idea/vcs.xml b/core/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/core/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/core/Cargo.toml b/core/Cargo.toml new file mode 100755 index 0000000..59ba23d --- /dev/null +++ b/core/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "core" +version = "0.1.0" +edition = "2018" +build = "build.rs" + +[lib] +name = "nativescript" +crate-type = ["dylib"] + + +[dependencies] +windows = "0.10.0" +rusty_v8 = "0.21.0" +bindings = { package = "core_bindings", path = "bindings" } +chrono = "0.4.19" +libc = "0.2.95" + +[build-dependencies] +windows = "0.10.0" +cc = "1.0" +bindgen = "0.53.1" diff --git a/core/bindings/Cargo.toml b/core/bindings/Cargo.toml new file mode 100755 index 0000000..a237d08 --- /dev/null +++ b/core/bindings/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "core_bindings" +version = "0.1.0" +edition = "2018" + +[dependencies] +windows = "0.10.0" + +[build-dependencies] +windows = "0.10.0" \ No newline at end of file diff --git a/core/bindings/build.rs b/core/bindings/build.rs new file mode 100755 index 0000000..1c54dd8 --- /dev/null +++ b/core/bindings/build.rs @@ -0,0 +1,10 @@ +fn main() { + windows::build!( + Windows::Win32::System::Console::WriteConsoleA, + Windows::Win32::System::WindowsProgramming::STD_OUTPUT_HANDLE, + Windows::Win32::System::WindowsProgramming::GetStdHandle, + Windows::Win32::System::SystemServices::GetProcAddress, + Windows::Win32::System::SystemServices::LoadLibraryA, + Windows::Win32::System::SystemServices::FARPROC + ); +} \ No newline at end of file diff --git a/core/bindings/src/lib.rs b/core/bindings/src/lib.rs new file mode 100755 index 0000000..7e2815a --- /dev/null +++ b/core/bindings/src/lib.rs @@ -0,0 +1 @@ +windows::include_bindings!(); \ No newline at end of file diff --git a/core/build.rs b/core/build.rs new file mode 100755 index 0000000..884ae12 --- /dev/null +++ b/core/build.rs @@ -0,0 +1,33 @@ +use std::env; + +use std::path::PathBuf; + +fn main() { + let mut build = cc::Build::default() ; + build.file("src/bindings.cpp") + .cpp(true) + .include("C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.8\\Include\\um") + .static_crt(true) + .compile("libcorebindings"); + + println!("cargo:rerun-if-changed=src/bindings.cpp"); + + +/* + let bindgen = bindgen::builder() + .clang_args(&["-I", "C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.8\\Include\\um"]) + .header("src/bindings.cpp") + // Tell cargo to invalidate the built crate whenever any of the + // included header files changed. + .parse_callbacks(Box::new(bindgen::CargoCallbacks)) + // Finish the builder and generate the bindings. + .generate() + // Unwrap the Result and panic on failure. + .expect("Unable to generate bindings"); + + // Write the bindings to the $OUT_DIR/bindings.rs file. + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindgen + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!");*/ +} \ No newline at end of file diff --git a/core/src/bindings.cpp b/core/src/bindings.cpp new file mode 100755 index 0000000..8bc54dc --- /dev/null +++ b/core/src/bindings.cpp @@ -0,0 +1,91 @@ +#include "headers.h" + + +typedef HRESULT (__cdecl * ProcRoGetMetaDataFile)(const HSTRING name, IMetaDataDispenserEx *, HSTRING *, IMetaDataImport2 **, mdTypeDef *typeDefToken); + + +extern "C" HRESULT Rometadataresolution_RoGetMetaDataFile(const HSTRING name, void* metaDataDispenser, void* metaDataFilePath, void** metaDataImport, mdTypeDef *typeDefToken){ + auto dispenser = reinterpret_cast(metaDataDispenser); + auto filePath = reinterpret_cast(metaDataFilePath); + auto import = (IMetaDataImport2 **)(metaDataImport); + + auto proc = (ProcRoGetMetaDataFile)GetProcAddress( + LoadLibraryA("api-ms-win-ro-typeresolution-l1-1-0.dll"), + "RoGetMetaDataFile" + ); + + return proc(name, dispenser, filePath, import, typeDefToken); +} + +extern "C" void IMetaDataImport2_GetTypeDefProps(void* metadata, uint32_t mdTypeDef, void* szTypeDef, ULONG cchTypeDef, ULONG * pchTypeDef , DWORD * pdwTypeDefFlags, mdToken * ptkExtends) { + auto meta = static_cast(metadata); + auto data = reinterpret_cast(szTypeDef); + meta->GetTypeDefProps(mdTypeDef, data, cchTypeDef, pchTypeDef, pdwTypeDefFlags, ptkExtends); +} + +extern "C" void IMetaDataImport2_GetTypeDefPropsNameSize(void* metadata, uint32_t token, ULONG * pchTypeDef) { + auto meta = static_cast(metadata); + auto size = reinterpret_cast(&pchTypeDef); + auto result = meta->GetTypeDefProps(token, 0, 0, size, 0, 0); +} + + +extern "C" void IMetaDataImport2_EnumInterfaceImpls(void* meta, mdToken token) { + auto metadata = reinterpret_cast(meta); + HCORENUM enumerator{ nullptr }; + ULONG count{ 0 }; + std::array tokens; + assert(metadata->EnumInterfaceImpls(&enumerator, token, tokens.data(), tokens.size(), &count)); + assert(count < tokens.size() - 1); + metadata->CloseEnum(enumerator); + std::cout << "count " << count << "\n"; + + //vector> result; + for (size_t i = 0; i < count; ++i) { + mdToken interfaceToken{ mdTokenNil }; + assert(metadata->GetInterfaceImplProps(tokens[i], nullptr, &interfaceToken)); + + //result.push_back(DeclarationFactory::makeInterfaceDeclaration(metadata, interfaceToken)); + } + + + // return result; + + +} + + +extern "C" ULONG32 Enums_TypeFromToken(mdToken token) { + return TypeFromToken(token); +} + + +extern "C" ULONG Helpers_Get_Type_Name(void* meta , mdToken token,uint16_t * nameData, size_t nameSize) { + auto metadata = reinterpret_cast(meta); + ULONG nameLength{ 0 }; + auto data = reinterpret_cast(nameData); + + switch (TypeFromToken(token)) { + case CorTokenType::mdtTypeDef: { + metadata->GetTypeDefProps(token, data, nameSize, &nameLength, nullptr, nullptr); + break; + } + case CorTokenType::mdtTypeRef: { + metadata->GetTypeRefProps(token, nullptr, data, nameSize, &nameLength); + break; + } + default: + assert(); + break; + } + + return nameLength - 1; +} + +extern "C" BOOL Helpers_IsTdPublic(DWORD value){ + return IsTdPublic(value); +} + +extern "C" BOOL Helpers_IsTdSpecialName(DWORD value){ + return IsTdSpecialName(value); +} \ No newline at end of file diff --git a/core/src/bindings.rs b/core/src/bindings.rs new file mode 100644 index 0000000..2d70f58 --- /dev/null +++ b/core/src/bindings.rs @@ -0,0 +1,60 @@ +use prelude::*; + +extern { + fn Rometadataresolution_RoGetMetaDataFile( + name: windows::HSTRING, meta_data_dispenser: *const c_void, meta_data_file_path: *const c_void, meta_data_import: *mut *mut c_void, type_def_token: *mut u32, + ) -> c_long; + + fn IMetaDataImport2_GetTypeDefProps(metadata: *const c_void, md_type_def: c_uint, sz_type_def: *mut c_void, cch_type_def: i64, pch_type_def: *mut i64, pdw_type_def_flags: *mut i64, md_token: *mut u32) -> windows::HRESULT; + + fn IMetaDataImport2_GetTypeDefPropsNameSize(metadata: *const c_void, md_type_def: c_uint, pch_type_def: *mut i64); + + fn IMetaDataImport2_EnumInterfaceImpls(metadata: *const c_void, md_type_def: c_uint); + + fn Enums_TypeFromToken(token: mdToken) -> ULONG; + + fn Helpers_Get_Type_Name(meta: *const c_void, md_token: mdToken, name: *mut libc::wchar_t, size: usize) -> ULONG; + + fn Helpers_IsTdPublic(value: DWORD) -> bool; + + fn Helpers_IsTdSpecialName(value: DWORD) -> bool; +} + + +pub mod rometadataresolution { + fn ro_get_meta_data_file( + name: windows::HSTRING, meta_data_dispenser: *const c_void, meta_data_file_path: *const c_void, meta_data_import: *mut *mut c_void, type_def_token: *mut u32, + ) -> c_long { + Rometadataresolution_RoGetMetaDataFile(name, meta_data_dispenser, meta_data_file_path, meta_data_import, type_def_token) + } +} + +pub mod imeta_data_import2 { + fn get_type_def_props(metadata: *const c_void, md_type_def: c_uint, sz_type_def: *mut c_void, cch_type_def: i64, pch_type_def: *mut i64, pdw_type_def_flags: *mut i64, md_token: *mut u32) { + IMetaDataImport2_GetTypeDefProps(metadata, md_type_def, sz_type_def, cch_type_def, pch_type_def, pdw_type_def_flags, md_token) + } + + fn get_type_def_props_name_size(metadata: *const c_void, md_type_def: c_uint, pch_type_def: *mut i64) { + IMetaDataImport2_GetTypeDefPropsNameSize(metadata, md_type_def, pch_type_def) + } +} + +pub mod enums { + fn type_from_token(token: mdToken) -> ULONG { + Enums_TypeFromToken(token) + } +} + +pub mod helpers { + fn get_type_name(meta: *const c_void, md_token: mdToken, name: *mut libc::wchar_t, size: usize) -> ULONG { + Helpers_Get_Type_Name(meta, md_token, name, size) + } + + fn is_td_public(value: DWORD) -> bool { + Helpers_IsTdPublic(value) + } + + fn is_td_special_name(value: DWORD) -> bool { + Helpers_IsTdSpecialName(value) + } +} \ No newline at end of file diff --git a/core/src/headers.h b/core/src/headers.h new file mode 100755 index 0000000..0c326f1 --- /dev/null +++ b/core/src/headers.h @@ -0,0 +1,10 @@ +#include +#include +# define NDEBUG +#include +#include +#include +#include +#include +const size_t MAX_IDENTIFIER_LENGTH{ 511 }; +using identifier = std::array; \ No newline at end of file diff --git a/core/src/lib.rs b/core/src/lib.rs new file mode 100755 index 0000000..993d0dd --- /dev/null +++ b/core/src/lib.rs @@ -0,0 +1,9 @@ +pub mod runtime; +pub mod metadata; +pub mod bindings; + +#[no_mangle] +pub extern fn hello(){ + println!("Hello from rust") +} + diff --git a/core/src/metadata/com_helpers.rs b/core/src/metadata/com_helpers.rs new file mode 100755 index 0000000..74beb85 --- /dev/null +++ b/core/src/metadata/com_helpers.rs @@ -0,0 +1,61 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +use std::ffi::c_void; +use crate::runtime::metadata::token_type::CorTokenType; +use crate::runtime::Enums_TypeFromToken; + + +pub type DWORD = u32; +pub type MdToken = u32; + + +#[repr(C)] +#[allow(camel_case)] +pub struct IMetaDataImport2 { + GetTypeDefProps: extern fn(MdToken, *mut i8, u64, *mut u64, DWORD, *mut MdToken) -> windows::HRESULT, + GetTypeRefProps: extern fn(MdToken, *mut MdToken, *mut i8, u64, *mut u64) -> windows::HRESULT, +} + +impl IMetaDataImport2 { + pub(crate) fn GetTypeDefProps(&mut self, mdTypeDef: MdToken, szTypeDef: &mut String, pchTypeDef: *mut u64, pdwTypeDefFlags: DWORD, ptkExtends: *mut MdToken) -> windows::HRESULT { + println!("mdTypeDef: {} szTypeDef: {} pchTypeDef: {} pdwTypeDefFlags: {} ptkExtends: {}", mdTypeDef, &szTypeDef, pchTypeDef as u64, pdwTypeDefFlags, ptkExtends as u32); + (self.GetTypeDefProps)(mdTypeDef, szTypeDef.as_mut_ptr() as *mut i8, szTypeDef.len() as u64, pchTypeDef, pdwTypeDefFlags, ptkExtends) + } + fn GetTypeRefProps(&mut self, tkTypeRef: MdToken, mut ptkResolutionScope: MdToken, szName: &mut String, pchName: *mut u64) -> windows::HRESULT { + (self.GetTypeRefProps)(tkTypeRef, &mut ptkResolutionScope, szName.as_mut_ptr() as *mut i8, szName.len() as u64, pchName) + } +} + +pub(crate) fn get_type_name(metadata: *mut c_void, md_token: u32) -> String { + assert!(!metadata.is_null()); + assert!(md_token == 0); + let mut name_data = String::new(); + let mut name_length = 0_u64; + + let mut metadata: *mut IMetaDataImport2 = unsafe {std::mem::transmute(metadata)}; + let mut metadata = unsafe { &mut *metadata }; + unsafe { + println!("asdasda {:?}", Enums_TypeFromToken(md_token)); + match Enums_TypeFromToken(md_token).into() { + CorTokenType::MdtTypeDef => { + println!("MdtTypeDef"); + assert!(metadata.GetTypeDefProps(md_token, &mut name_data, &mut name_length, 0, &mut 0).is_err()) + } + CorTokenType::MdtTypeRef => { + println!("MdtTypeRef"); + assert!(metadata.GetTypeRefProps(md_token, 0, &mut name_data, &mut name_length).is_err()) + } + _ => { + assert!(true) + } + } + } + + println!("name_data {:?} : name_length {:?}", &name_data, name_length); + + return name_data +} + +fn get_type_def_props() {} \ No newline at end of file diff --git a/core/src/metadata/declarations/declaration.rs b/core/src/metadata/declarations/declaration.rs new file mode 100644 index 0000000..0f51a63 --- /dev/null +++ b/core/src/metadata/declarations/declaration.rs @@ -0,0 +1,32 @@ +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum DeclarationKind { + Namespace, + Class, + Interface, + GenericInterface, + GenericInterfaceInstance, + Enum, + EnumMember, + Struct, + StructField, + Delegate, + GenericDelegate, + GenericDelegateInstance, + Event, + Property, + Method, + Parameter, +} + +pub trait Declaration { + fn is_exported(&self) -> bool; + + /// Specifies the simple name (e.g., "String" rather than "System.String") of a given type. + fn name<'a>(&self) -> &'a str ; + + /// Specifies the fully-qualified name of a given type. + /// For generic types, this includes the spelling of generic parameter names. + fn full_name<'a>(&self) -> &'a str; + + fn kind(&self) -> DeclarationKind; +} diff --git a/core/src/metadata/declarations/enum_declaration.rs b/core/src/metadata/declarations/enum_declaration.rs new file mode 100644 index 0000000..012ece8 --- /dev/null +++ b/core/src/metadata/declarations/enum_declaration.rs @@ -0,0 +1,27 @@ +use crate::prelude::*; + +use super::{ + declaration::{ + Declaration, + DeclarationKind, + }, + type_declaration::TypeDeclaration, +}; + +pub struct EnumDeclaration { + type_declaration: TypeDeclaration, +} + +impl Declaration for EnumDeclaration { + fn kind(&self) -> DeclarationKind { + self.type_declaration.kind + } +} + +impl EnumDeclaration { + pub fn new(metadata: *const c_void, token: mdTypeDef) -> Self { + Self { + type_declaration: TypeDeclaration::new(DeclarationKind::Enum, metadata, token) + } + } +} \ No newline at end of file diff --git a/core/src/metadata/declarations/field_declaration.rs b/core/src/metadata/declarations/field_declaration.rs new file mode 100644 index 0000000..e8854bb --- /dev/null +++ b/core/src/metadata/declarations/field_declaration.rs @@ -0,0 +1,66 @@ +use super::declaration::{Declaration, DeclarationKind}; +use crate::prelude::*; + +use crate::bindings::{ + imeta_data_import2, + helpers, + enums +}; +use std::marker; +use std::ffi::{OsString}; + +pub struct FieldDeclaration <'a>{ + pub kind: DeclarationKind, + pub metadata: *const c_void, + pub token: mdTypeDef, + _marker: marker::PhantomData<&'a *const c_void> +} + +impl Declaration for FieldDeclaration { + fn kind(&self) -> DeclarationKind{ + self.kind + } + + fn is_exported(&self) -> bool { + let mut flags: DWORD = 0; + assert( + imeta_data_import2::get_type_def_props( + self.token, 0, 0,0, &mut flags, 0 + ).is_ok() + ); + + if !helpers::is_td_public(flags) || helpers::is_td_special_name(flags) { + return false; + } + + return true; + } + + fn name<'b>(&self) -> &'b str { + return self.full_name(); + } + + fn full_name<'b>(&self) -> &'b str { + let mut full_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + + let length = helpers::(self.metadata, self.token, full_name_data.as_mut_ptr(), full_name_data.len()); + full_name_data.resize(length as usize, 0); + OsString::from_wide(name.as_slice()) + } +} + +impl FieldDeclaration { + pub fn new(kind: DeclarationKind, metadata: *const c_void, token: mdTypeDef) -> Self { + let value = Self { + kind, + metadata, + token, + _marker: marker::PhantomData + }; + + assert!(value.metadata.is_not_null()); + assert!(enums::type_from_token(value.token) == mdtFieldDef); + assert!(value.token != mdTypeDefNil); + value + } +} \ No newline at end of file diff --git a/core/src/metadata/declarations/mod.rs b/core/src/metadata/declarations/mod.rs new file mode 100644 index 0000000..4e92ff0 --- /dev/null +++ b/core/src/metadata/declarations/mod.rs @@ -0,0 +1,4 @@ +pub mod declaration; +pub mod type_declaration; +pub mod field_declaration; +pub mod enum_declaration; \ No newline at end of file diff --git a/core/src/metadata/declarations/type_declaration.rs b/core/src/metadata/declarations/type_declaration.rs new file mode 100644 index 0000000..cc339ad --- /dev/null +++ b/core/src/metadata/declarations/type_declaration.rs @@ -0,0 +1,79 @@ +use crate::prelude::*; +use super::declaration::{Declaration, DeclarationKind}; +use crate::bindings::{ + imeta_data_import2, + helpers, + enums +}; +use std::marker; +use std::ffi::{OsString}; + + +pub struct TypeDeclaration <'a>{ + pub kind: DeclarationKind, + pub metadata: *const c_void, + pub token: mdTypeDef, + _marker: marker::PhantomData<&'a *const c_void> +} + + +impl Declaration for TypeDeclaration { + fn kind(&self) -> DeclarationKind{ + self.kind + } + + fn is_exported(&self) -> bool { + let mut flags: DWORD = 0; + assert( + imeta_data_import2::get_type_def_props( + self.token, 0, 0,0, &mut flags, 0 + ).is_ok() + ); + + if !helpers::is_td_public(flags) || helpers::is_td_special_name(flags) { + return false; + } + + return true; + } + + fn name<'b>(&self) -> &'b str { + let mut name = self.full_name(); + + // size_t backtickIndex{ fullyQualifiedName.rfind(L"`") }; + // if (backtickIndex != wstring::npos) { + // fullyQualifiedName.erase(backtickIndex); + // } + // + // size_t dotIndex{ fullyQualifiedName.rfind(L".") }; + // if (dotIndex != wstring::npos) { + // fullyQualifiedName.erase(0, dotIndex + 1); + // } + + return name; + } + + fn full_name<'b>(&self) -> &'b str { + let mut full_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + + let length = Helpers_Get_Type_Name(self.metadata, self.token, full_name_data.as_mut_ptr(), full_name_data.len()); + full_name_data.resize(length as usize, 0); + OsString::from_wide(name.as_slice()) + } +} + +impl TypeDeclaration { + pub fn new(kind: DeclarationKind, metadata: *const c_void, token: mdTypeDef) -> Self { + let value = Self { + kind, + metadata, + token, + _marker: marker::PhantomData + }; + + assert!(value.metadata.is_not_null()); + assert!(enums::type_from_token(value.token) == mdtTypeDef); + assert!(value.token != mdTypeDefNil); + value + } +} \ No newline at end of file diff --git a/core/src/metadata/mod.rs b/core/src/metadata/mod.rs new file mode 100755 index 0000000..599bbc0 --- /dev/null +++ b/core/src/metadata/mod.rs @@ -0,0 +1,10 @@ +pub mod com_helpers; +pub mod token_type; + +pub struct MetadataReader {} + +impl MetadataReader { + pub fn find_by_name(&self){ + + } +} \ No newline at end of file diff --git a/core/src/metadata/token_type.rs b/core/src/metadata/token_type.rs new file mode 100755 index 0000000..5e00072 --- /dev/null +++ b/core/src/metadata/token_type.rs @@ -0,0 +1,64 @@ +#[derive(Debug, Clone, Copy)] +pub enum CorTokenType { + MdtModule = 0x00000000, + MdtTypeRef = 0x01000000, + MdtTypeDef = 0x02000000, + MdtFieldDef = 0x04000000, + MdtMethodDef = 0x06000000, + MdtParamDef = 0x08000000, + MdtInterfaceImpl = 0x09000000, + MdtMemberRef = 0x0a000000, + MdtCustomAttribute = 0x0c000000, + MdtPermission = 0x0e000000, + MdtSignature = 0x11000000, + MdtEvent = 0x14000000, + MdtProperty = 0x17000000, + MdtModuleRef = 0x1a000000, + MdtTypeSpec = 0x1b000000, + MdtAssembly = 0x20000000, + MdtAssemblyRef = 0x23000000, + MdtFile = 0x26000000, + MdtExportedType = 0x27000000, + MdtManifestResource = 0x28000000, + MdtGenericParam = 0x2a000000, + MdtMethodSpec = 0x2b000000, + MdtGenericParamConstraint = 0x2c000000, + MdtString = 0x70000000, + MdtName = 0x71000000, + MdtBaseType = 0x72000000, + MdtError_ = 1868 +} + +impl From for CorTokenType { + fn from(value: u32) -> Self { + match value { + 0x00000000 => Self::MdtModule, + 0x01000000 => Self::MdtTypeRef, + 0x02000000 => Self::MdtTypeDef, + 0x04000000 => Self::MdtFieldDef, + 0x06000000 => Self::MdtMethodDef, + 0x08000000 => Self::MdtParamDef, + 0x09000000 => Self::MdtInterfaceImpl, + 0x0a000000 => Self::MdtMemberRef, + 0x0c000000 => Self::MdtCustomAttribute, + 0x0e000000 => Self::MdtPermission, + 0x11000000 => Self::MdtSignature, + 0x14000000 => Self::MdtEvent, + 0x17000000 => Self::MdtProperty, + 0x1a000000 => Self::MdtModuleRef, + 0x1b000000 => Self::MdtTypeSpec, + 0x20000000 => Self::MdtAssembly, + 0x23000000 => Self::MdtAssemblyRef, + 0x26000000 => Self::MdtFile, + 0x27000000 => Self::MdtExportedType, + 0x28000000 => Self::MdtManifestResource, + 0x2a000000 => Self::MdtGenericParam, + 0x2b000000 => Self::MdtMethodSpec, + 0x2c000000 => Self::MdtGenericParamConstraint, + 0x70000000 => Self::MdtString, + 0x71000000 => Self::MdtName, + 0x72000000 => Self::MdtBaseType, + _ => Self::MdtError_ + } + } +} \ No newline at end of file diff --git a/core/src/prelude.rs b/core/src/prelude.rs new file mode 100644 index 0000000..d093a58 --- /dev/null +++ b/core/src/prelude.rs @@ -0,0 +1,32 @@ +pub type ULONG32 = ::std::os::raw::c_uint; +pub type DWORD = ::std::os::raw::c_ulong; +pub type ULONG = ::std::os::raw::c_ulong; +pub type mdScope = LPVOID; +pub type mdToken = ULONG32; +pub type mdModule = mdToken; +pub type mdTypeRef = mdToken; +pub type mdTypeDef = mdToken; +pub type mdFieldDef = mdToken; +pub type mdMethodDef = mdToken; +pub type mdParamDef = mdToken; +pub type mdInterfaceImpl = mdToken; +pub type mdMemberRef = mdToken; +pub type mdCustomAttribute = mdToken; +pub type mdPermission = mdToken; +pub type mdSignature = mdToken; +pub type mdEvent = mdToken; +pub type mdProperty = mdToken; +pub type mdModuleRef = mdToken; +pub type mdAssembly = mdToken; +pub type mdAssemblyRef = mdToken; +pub type mdFile = mdToken; +pub type mdExportedType = mdToken; +pub type mdManifestResource = mdToken; +pub type mdTypeSpec = mdToken; +pub type mdGenericParam = mdToken; +pub type mdMethodSpec = mdToken; +pub type mdGenericParamConstraint = mdToken; +pub type mdString = mdToken; +pub type mdCPToken = mdToken; +pub type RID = ULONG; +pub type LPVOID = *mut ::std::os::raw::c_void; \ No newline at end of file diff --git a/core/src/runtime/console.rs b/core/src/runtime/console.rs new file mode 100755 index 0000000..9f7cd7a --- /dev/null +++ b/core/src/runtime/console.rs @@ -0,0 +1,50 @@ + +use rusty_v8 as v8; +use bindings::{Windows::Win32::System::Console,Windows::Win32::System::WindowsProgramming}; +use std::ffi::{CString, c_void}; + +pub(crate) fn handle_console_log(scope: &mut v8::HandleScope, args: v8::FunctionCallbackArguments, _retval: v8::ReturnValue){ + let mut value = String::new(); + for i in 0..args.length() { + let item = args.get(i).to_rust_string_lossy(scope); + if i == args.length() - 1 { + value.push_str(&item) + } else { + value.push_str(&item); + value.push_str(",") + } + if i == args.length() - 1{ + value.push_str("\n"); + } + } + + let length = value.chars().count() as u32; + let handle = unsafe { WindowsProgramming::GetStdHandle(WindowsProgramming::STD_OUTPUT_HANDLE)}; + let string = CString::new(value).unwrap(); + let mut written = 0_u32; + unsafe { + Console::WriteConsoleA(handle, string.as_ptr() as *const c_void, length, &mut written, std::ptr::null_mut()); + } + +} + +pub(crate) fn handle_console_dir(scope: &mut v8::HandleScope, args: v8::FunctionCallbackArguments, _retval: v8::ReturnValue){ + let mut value = String::new(); + for i in 0..args.length() { + let item = args.get(i).to_rust_string_lossy(scope); + if i == args.length() - 1 { + value.push_str(&item) + } else { + value.push_str(&item); + value.push_str(",") + } + } + let length = value.chars().count() as u32; + let handle = unsafe { WindowsProgramming::GetStdHandle(WindowsProgramming::STD_OUTPUT_HANDLE)}; + + let string = CString::new(value).unwrap(); + let mut written = 0_u32; + unsafe { + Console::WriteConsoleA(handle, string.as_ptr() as *const c_void, length, &mut written, std::ptr::null_mut()); + } +} \ No newline at end of file diff --git a/core/src/runtime/ffi/mod.rs b/core/src/runtime/ffi/mod.rs new file mode 100755 index 0000000..e69de29 diff --git a/core/src/runtime/global.rs b/core/src/runtime/global.rs new file mode 100755 index 0000000..e69de29 diff --git a/core/src/runtime/mod.rs b/core/src/runtime/mod.rs new file mode 100755 index 0000000..aebe0de --- /dev/null +++ b/core/src/runtime/mod.rs @@ -0,0 +1,305 @@ +mod global; +mod ffi; +mod console; + +use rusty_v8 as v8; +use std::ffi::{CString, CStr, c_void, OsStr, OsString}; +use std::os::raw::{c_char, c_uint, c_long}; +use std::io::Read; +use std::os::windows::prelude::*; +use std::path::{Path, PathBuf}; +use crate::runtime::metadata::com_helpers::{get_type_name, IMetaDataImport2}; +use windows::HSTRING; + +pub struct Runtime { + isolate: v8::OwnedIsolate, + global_context: v8::Global, + app_root: String, +} + + +const MAX_IDENTIFIER_LENGTH: usize = 511; + + +impl Runtime { + pub fn new(app_root: &str) -> Self { + let platform = v8::new_default_platform().unwrap(); + v8::V8::initialize_platform(platform); + v8::V8::initialize(); + let mut isolate = v8::Isolate::new(Default::default()); + + isolate.set_capture_stack_trace_for_uncaught_exceptions(true, 100); + + let global_context; + { + let mut scope = &mut v8::HandleScope::new(&mut isolate); + let mut global = v8::FunctionTemplate::new(scope, Runtime::handle_global); + + { + let class_name = v8::String::new(scope, "NativeScriptGlobalObject").unwrap(); + global.set_class_name(class_name); + } + + let mut global_template = v8::ObjectTemplate::new_from_template(scope, global); + + { + { + Runtime::init_performance(scope, &mut global_template); + } + + { + Runtime::init_time(scope, &mut global_template); + } + + + let mut context = v8::Context::new_from_template(scope, global_template); + let mut local_scope = v8::ContextScope::new(scope, context); + + { + + Runtime::init_global(&mut local_scope, context); + } + + { + Runtime::init_console(&mut local_scope, context); + } + + { + Runtime::init_meta(&mut local_scope, context); + } + + { + global_context = v8::Global::new(&mut local_scope, context); + } + + } + } + + Self { + isolate, + global_context, + app_root: app_root.to_string(), + } + } + + fn run_script(&mut self, script: &str) { + /* + let path = PathBuf::from(script); + println!("??? {:?}", path.to_string_lossy()); + let mut file = std::fs::File::open(std::fs::canonicalize(&path).unwrap()).unwrap(); + let mut data = Vec::new(); + file.read_to_end(&mut data); + let script = String::from_utf8_lossy(data.as_slice()); + */ + + let mut isolate = &mut self.isolate; + let mut scope = &mut v8::HandleScope::new(isolate); + let mut local = v8::Local::new(scope, &self.global_context); + let mut scope = &mut v8::ContextScope::new(scope, local); + let code = v8::String::new(scope, script).unwrap(); + let script = v8::Script::compile(&mut scope, code, None).unwrap(); + let result = script.run(&mut scope).unwrap(); + let result = result.to_string(&mut scope).unwrap(); + } + + fn handle_global(_scope: &mut v8::HandleScope, _args: v8::FunctionCallbackArguments, _retval: v8::ReturnValue) {} + fn init_global(scope: &mut v8::ContextScope>, context: v8::Local) { + let mut global = context.global(scope); + let value = v8::String::new( + scope, "global", + ).unwrap().into(); + global.define_own_property(scope, value, global.into(), v8::READ_ONLY); + } + + fn init_console(scope: &mut v8::ContextScope>, context: v8::Local) { + let console = v8::Object::new(scope); + let log = v8::Function::new(scope, console::handle_console_log).unwrap(); + let dir = v8::Function::new(scope, console::handle_console_dir).unwrap(); + + { + let name = v8::String::new(scope, "log").unwrap().into(); + console.set( + scope, + name, + log.into(), + ); + } + + { + let name = v8::String::new(scope, "dir").unwrap().into(); + console.set( + scope, + name, + dir.into(), + ); + } + + let mut global = context.global(scope); + let value = v8::String::new( + scope, "console", + ).unwrap().into(); + global.define_own_property(scope, value, console.into(), v8::READ_ONLY); + } + + fn handle_time(scope: &mut v8::HandleScope, + _args: v8::FunctionCallbackArguments, + mut retval: v8::ReturnValue) { + let now = chrono::Utc::now(); + retval.set( + v8::Number::new(scope, (now.timestamp_millis() / 1000000) as f64).into() + ) + } + + fn init_time(scope: &mut v8::HandleScope<()>, global: &mut v8::Local) { + let time = v8::FunctionTemplate::new(scope, Runtime::handle_time); + global.set( + v8::String::new(scope, "time").unwrap().into(), time.into(), + ); + } + + fn init_performance(scope: &mut v8::HandleScope<()>, global: &mut v8::Local) { + let performance = v8::ObjectTemplate::new(scope); + let now = v8::FunctionTemplate::new(scope, Runtime::handle_now); + performance.set( + v8::String::new(scope, "now").unwrap().into(), + now.into(), + ); + global.set( + v8::String::new(scope, "performance").unwrap().into(), + performance.into(), + ); + } + + fn handle_now(scope: &mut v8::HandleScope, + _args: v8::FunctionCallbackArguments, + mut retval: v8::ReturnValue) { + let now = chrono::Utc::now(); + retval.set( + v8::Number::new(scope, now.timestamp_nanos() as f64).into() + ) + } + + fn init_meta(scope: &mut v8::ContextScope>, context: v8::Local) { + let meta = v8::Function::new(scope, Runtime::handle_meta).unwrap(); + let mut global = context.global(scope); + let value = v8::String::new( + scope, "$", + ).unwrap().into(); + global.define_own_property(scope, value, meta.into(), v8::READ_ONLY); + } + + fn handle_meta(scope: &mut v8::HandleScope, + args: v8::FunctionCallbackArguments, + mut retval: v8::ReturnValue) { + println!("handle meta {:?}", args.get(0).to_rust_string_lossy(scope)); + let typeres_dll = CString::new("api-ms-win-ro-typeresolution-l1-1-0.dll").unwrap(); + let method = CString::new("RoGetMetaDataFile").unwrap(); + + + let ro_get_meta_data_file: extern "stdcall" fn(windows::HSTRING, + *const c_void, + *const c_void, + *mut *mut c_void, + *mut u32 + ) -> windows::HRESULT; + + + + let proc = unsafe { + bindings::Windows::Win32::System::SystemServices::GetProcAddress( + bindings::Windows::Win32::System::SystemServices::LoadLibraryA( + "api-ms-win-ro-typeresolution-l1-1-0.dll" + ), + "RoGetMetaDataFile" + ) + }; + + ro_get_meta_data_file = unsafe { std::mem::transmute(proc) }; + + println!("RoGetMetaDataFile Address is {}", ro_get_meta_data_file as i64); + let class_name = args.get(0).to_rust_string_lossy(scope); + let mut metadata = std::ptr::null_mut() as *mut c_void; + let mut token = 0_u32; + let mut metadata_ptr: *mut *mut c_void = &mut metadata; + // let result = ro_get_meta_data_file( + // class_name.into(), + // std::ptr::null(), + // std::ptr::null(), + // metadata, + // &mut token + // ); + + let result = unsafe { + Rometadataresolution_RoGetMetaDataFile( + class_name.into(), + std::ptr::null(), + std::ptr::null(), + metadata_ptr, + &mut token + ) + }; + + + let COR_CTOR_METHOD_NAME =".ctor"; + + + println!("metadata is {:?}", metadata); + + println!("token is {:?}", token); + println!("result is {:?}", result); + + + + + + let mut md: *mut IMetaDataImport2 = unsafe {std::mem::transmute(metadata)}; + + unsafe { + let mut name = vec![0_u16;MAX_IDENTIFIER_LENGTH]; + let length = Helpers_Get_Type_Name(md as *const c_void, token, name.as_mut_ptr(), name.len()); + name.resize(length as usize, 0); + let name = OsString::from_wide(name.as_slice()); + println!("nameaa {:?}", name); + println!("val {:?}", name.to_string_lossy()); + } + // let mut md = unsafe { &mut *md }; + + let mut parent_token = 0_u32; + let mut string = String::new(); + let mut name_length = 0; + + unsafe { + // IMetaDataImport2_EnumInterfaceImpls(md as _, token); + // IMetaDataImport2_GetTypeDefPropsNameSize(md as _, token, &mut name_length); + } + + println!("name_length {}", name_length); + + // unsafe { IMetaDataImport2_GetTypeDefProps(md as _, token, string.as_mut_ptr() as *mut c_void, string.len() as i64, &mut name_length, 0 as _, &mut parent_token); } + + // md.GetTypeDefProps(token, &mut string, &mut name_length, 0, &mut parent_token); + + println!("parent token {:?}", parent_token); + + let type_name = get_type_name(metadata as *mut c_void, parent_token); + + println!("typename is {:?}", type_name); + } +} + + +#[no_mangle] +pub extern fn runtime_init(main_entry: *const c_char) -> i64 { + let string = unsafe { CStr::from_ptr(main_entry) }.to_string_lossy(); + Box::into_raw(Box::new(Runtime::new(string.as_ref()))) as i64 +} + +#[no_mangle] +pub extern fn runtime_runscript(runtime: i64, script: *const c_char) { + if runtime != 0 { + let mut runtime: *mut Runtime = runtime as _; + let mut runtime = unsafe { &mut *runtime }; + let script = unsafe { CStr::from_ptr(script) }.to_string_lossy(); + runtime.run_script(script.as_ref()); + } +} \ No newline at end of file From 7d966c22720eb27c897b59d598c1ad5e73d49b7e Mon Sep 17 00:00:00 2001 From: Osei Fortune Date: Sun, 6 Jun 2021 20:08:21 -0400 Subject: [PATCH 03/11] updates --- .gitignore | 5 +- .idea/.gitignore | 8 + .idea/codeStyles/codeStyleConfig.xml | 5 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + .idea/windows-runtime.iml | 27 + Cargo.toml | 2 +- {core/bindings => core-bindings}/Cargo.toml | 23 +- core-bindings/build.rs | 62 ++ core-bindings/src/bindings.cpp | 561 +++++++++++++++ {core => core-bindings}/src/headers.h | 25 +- core-bindings/src/lib.rs | 26 + core/Cargo.toml | 9 +- core/bindings/build.rs | 10 - core/bindings/src/lib.rs | 1 - core/build.rs | 33 - core/src/bindings.cpp | 91 --- core/src/bindings.rs | 641 ++++++++++++++++-- core/src/enums.rs | 211 ++++++ core/src/lib.rs | 4 +- core/src/metadata/com_helpers.rs | 123 ++-- core/src/metadata/declaration_factory.rs | 93 +++ .../declarations/base_class_declaration.rs | 238 +++++++ .../declarations/class_declaration.rs | 141 ++++ core/src/metadata/declarations/declaration.rs | 55 +- .../declarations/delegate_declaration/mod.rs | 161 +++++ .../metadata/declarations/enum_declaration.rs | 19 +- .../declarations/event_declaration.rs | 129 ++++ .../declarations/field_declaration.rs | 45 +- .../declarations/interface_declaration.rs | 212 ++++++ .../declarations/method_declaration.rs | 192 ++++++ core/src/metadata/declarations/mod.rs | 13 +- .../declarations/namespace_declaration.rs | 47 ++ .../declarations/parameter_declaration.rs | 55 ++ .../declarations/property_declaration.rs | 148 ++++ .../declarations/struct_declaration.rs | 66 ++ .../declarations/struct_field_declaration.rs | 54 ++ .../metadata/declarations/type_declaration.rs | 128 ++-- .../metadata/generic_instance_id_builder.rs | 156 +++++ core/src/metadata/meta_data_reader.rs | 138 ++++ core/src/metadata/mod.rs | 14 +- core/src/metadata/signature.rs | 151 +++++ core/src/metadata/token_type.rs | 64 -- core/src/prelude.rs | 79 ++- 44 files changed, 3807 insertions(+), 472 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/windows-runtime.iml rename {core/bindings => core-bindings}/Cargo.toml (65%) mode change 100755 => 100644 create mode 100644 core-bindings/build.rs create mode 100644 core-bindings/src/bindings.cpp rename {core => core-bindings}/src/headers.h (71%) mode change 100755 => 100644 create mode 100644 core-bindings/src/lib.rs delete mode 100755 core/bindings/build.rs delete mode 100755 core/bindings/src/lib.rs delete mode 100755 core/build.rs delete mode 100755 core/src/bindings.cpp create mode 100644 core/src/enums.rs create mode 100644 core/src/metadata/declaration_factory.rs create mode 100644 core/src/metadata/declarations/base_class_declaration.rs create mode 100644 core/src/metadata/declarations/class_declaration.rs create mode 100644 core/src/metadata/declarations/delegate_declaration/mod.rs create mode 100644 core/src/metadata/declarations/event_declaration.rs create mode 100644 core/src/metadata/declarations/interface_declaration.rs create mode 100644 core/src/metadata/declarations/method_declaration.rs create mode 100644 core/src/metadata/declarations/namespace_declaration.rs create mode 100644 core/src/metadata/declarations/parameter_declaration.rs create mode 100644 core/src/metadata/declarations/property_declaration.rs create mode 100644 core/src/metadata/declarations/struct_declaration.rs create mode 100644 core/src/metadata/declarations/struct_field_declaration.rs create mode 100644 core/src/metadata/generic_instance_id_builder.rs create mode 100644 core/src/metadata/meta_data_reader.rs create mode 100644 core/src/metadata/signature.rs delete mode 100755 core/src/metadata/token_type.rs diff --git a/.gitignore b/.gitignore index 519caa8..9ef481f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,7 @@ /**/*.rs.bk /Cargo.lock .DS_Store -.vs \ No newline at end of file +.vs + +[Bb]in/ +[Oo]bj/ \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..73f69e0 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..4768290 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/windows-runtime.iml b/.idea/windows-runtime.iml new file mode 100644 index 0000000..a179829 --- /dev/null +++ b/.idea/windows-runtime.iml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 30cf9b6..bac9d82 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] -members = ["core"] +members = ["core", "core-bindings"] [profile.release] panic = "abort" diff --git a/core/bindings/Cargo.toml b/core-bindings/Cargo.toml old mode 100755 new mode 100644 similarity index 65% rename from core/bindings/Cargo.toml rename to core-bindings/Cargo.toml index a237d08..4abc516 --- a/core/bindings/Cargo.toml +++ b/core-bindings/Cargo.toml @@ -1,10 +1,13 @@ -[package] -name = "core_bindings" -version = "0.1.0" -edition = "2018" - -[dependencies] -windows = "0.10.0" - -[build-dependencies] -windows = "0.10.0" \ No newline at end of file +[package] +name = "core_bindings" +version = "0.1.0" +edition = "2018" +build = "build.rs" + +[dependencies] +windows = "0.10.0" + +[build-dependencies] +windows = "0.10.0" +cc = "1.0" +bindgen = "0.53.1" \ No newline at end of file diff --git a/core-bindings/build.rs b/core-bindings/build.rs new file mode 100644 index 0000000..fa43418 --- /dev/null +++ b/core-bindings/build.rs @@ -0,0 +1,62 @@ +use std::env; + +use std::path::PathBuf; +use bindgen::EnumVariation; + + +fn main() { + windows::build!( + Windows::Win32::System::Console::WriteConsoleA, + Windows::Win32::System::WindowsProgramming::STD_OUTPUT_HANDLE, + Windows::Win32::System::WindowsProgramming::GetStdHandle, + Windows::Win32::System::SystemServices::GetProcAddress, + Windows::Win32::System::SystemServices::LoadLibraryA, + Windows::Win32::System::SystemServices::FARPROC + ); + + let mut build = cc::Build::default() ; + build.file("src/bindings.cpp") + .cpp(true) + .include("C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.8\\Include\\um") + .static_crt(true) + .compile("libcorebindings"); + + println!("cargo:rerun-if-changed=src/bindings.cpp"); + + + + let bindgen = bindgen::builder() + .generate_comments(false) + .default_enum_style( + EnumVariation::Rust { + non_exhaustive: false + } + ) + .size_t_is_usize(true) + .use_core() + .clang_arg("-std=c++17") + .clang_args(&["-x", "c++"]) + .clang_arg("-v") + .whitelist_function("Rometadataresolution_.*") + .whitelist_function("IMetaDataImport2_.*") + .whitelist_function("Enums_.*") + .whitelist_function("Helpers_.*") + .whitelist_var("Helpers_.*") + .blacklist_type("HSTRING") + .raw_line("pub type HSTRING = *mut windows::HSTRING;") + .clang_args(&["-I", "C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.8\\Include\\um"]) + .header("src/bindings.cpp") + // Tell cargo to invalidate the built crate whenever any of the + // included header files changed. + .parse_callbacks(Box::new(bindgen::CargoCallbacks)) + // Finish the builder and generate the bindings. + .generate() + // Unwrap the Result and panic on failure. + .expect("Unable to generate bindings"); + + // Write the bindings to the $OUT_DIR/bindings.rs file. + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindgen + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!"); +} \ No newline at end of file diff --git a/core-bindings/src/bindings.cpp b/core-bindings/src/bindings.cpp new file mode 100644 index 0000000..5f61f1d --- /dev/null +++ b/core-bindings/src/bindings.cpp @@ -0,0 +1,561 @@ +#include "headers.h" + + +typedef HRESULT (__cdecl *ProcRoGetMetaDataFile)(const HSTRING name, IMetaDataDispenserEx *, HSTRING *, + IMetaDataImport2 **, mdTypeDef *typeDefToken); + + +typedef HRESULT(__cdecl *ProcRoParseTypeName)(const HSTRING typeName, DWORD *partsCount, HSTRING **typeNameParts); + +typedef HRESULT(__cdecl *ProcRoGetParameterizedTypeInstanceIID)(UINT32 nameElementCount, + PCWSTR *nameElements, + const IRoMetaDataLocator &metaDataLocator, + GUID *iid, + ROPARAMIIDHANDLE *pExtra); + + +extern "C" HRESULT +Rometadataresolution_RoGetMetaDataFile(const HSTRING name, void *metaDataDispenser, void *metaDataFilePath, + void **metaDataImport, mdTypeDef *typeDefToken) { + auto dispenser = reinterpret_cast(metaDataDispenser); + auto filePath = reinterpret_cast(metaDataFilePath); + auto import = (IMetaDataImport2 * *)(metaDataImport); + + /* auto proc = (ProcRoGetMetaDataFile)GetProcAddress( + LoadLibraryA("api-ms-win-ro-typeresolution-l1-1-0.dll"), + "RoGetMetaDataFile"); + + return proc(name, dispenser, filePath, import, typeDefToken); + */ + + return RoGetMetaDataFile(name, dispenser, filePath, import, typeDefToken); +} + + +extern "C" HRESULT +Rometadataresolution_RoParseTypeName(const HSTRING typeName, DWORD *partsCount, HSTRING **typeNameParts) { + /*auto proc = (ProcRoParseTypeName)GetProcAddress( + LoadLibraryA("api-ms-win-ro-typeresolution-l1-1-0.dll"), + "RoParseTypeName"); + + return proc(typeName, partsCount, typeNameParts);*/ + return RoParseTypeName(typeName, partsCount, typeNameParts); +} + +extern "C" HRESULT Rometadataresolution_RoGetParameterizedTypeInstanceIID(UINT32 nameElementCount, + PCWSTR *nameElements, + const IRoMetaDataLocator &metaDataLocator, + GUID *iid, + ROPARAMIIDHANDLE *pExtra) { + /*auto proc = (ProcRoGetParameterizedTypeInstanceIID)GetProcAddress( + LoadLibraryA("api-ms-win-ro-typeresolution-l1-1-0.dll"), + "ro_get_parameterized_type_instance_iid"); + + return proc(nameElementCount, nameElements, metaDataLocator, iid, pExtra); */ + + return RoGetParameterizedTypeInstanceIID(nameElementCount, nameElements, metaDataLocator, iid, pExtra); +} + +//typedef HRESULT(void* RoLocator)(PCWSTR name, IRoSimpleMetaDataBuilder& builder); + + +//typedef HRESULT(*RoLocator)(PCWSTR name, IRoSimpleMetaDataBuilder& builder); + +struct _locator { + Ro::detail::_Locator locator; +}; + + +extern "C" void +Rometadataresolution_Ro_Locator(HRESULT(*fn)(PCWSTR name, IRoSimpleMetaDataBuilder &builder), Locator *locator) { + /*auto proc = (ProcRoGetParameterizedTypeInstanceIID)GetProcAddress( + LoadLibraryA("api-ms-win-ro-typeresolution-l1-1-0.dll"), + "ro_get_parameterized_type_instance_iid"); + + return proc(nameElementCount, nameElements, metaDataLocator, iid, pExtra); */ + locator->locator = Ro::Locator(fn); +} + + + +extern "C" HRESULT IMetaDataImport2_GetMethodProps(void *metadata, + mdMethodDef tkMethodDef, + mdTypeDef *ptkClass, + LPWSTR szMethod, + ULONG cchMethod, + ULONG *pchMethod, + DWORD *pdwAttr, + PCCOR_SIGNATURE *ppvSigBlob, + ULONG *pcbSigBlob, + ULONG *pulCodeRVA, + DWORD *pdwImplFlags) { + auto meta = static_cast(metadata); + return meta->GetMethodProps(tkMethodDef, ptkClass, szMethod, cchMethod, pchMethod, pdwAttr, ppvSigBlob, pcbSigBlob, + pulCodeRVA, pdwImplFlags); +} + +extern "C" HRESULT IMetaDataImport2_GetPropertyProps(void *metadata, mdProperty prop, + mdTypeDef *pClass, + LPCWSTR szProperty, + ULONG cchProperty, + ULONG *pchProperty, + DWORD *pdwPropFlags, + PCCOR_SIGNATURE *ppvSig, + ULONG *pbSig, + DWORD *pdwCPlusTypeFlag, + UVCP_CONSTANT *ppDefaultValue, + ULONG *pcchDefaultValue, + mdMethodDef *pmdSetter, + mdMethodDef *pmdGetter, + mdMethodDef *rmdOtherMethod, + ULONG cMax, + ULONG *pcOtherMethod) { + auto meta = static_cast(metadata); + return meta->GetPropertyProps(prop, pClass, szProperty, cchProperty, pchProperty, pdwPropFlags, ppvSig, pbSig, + pdwCPlusTypeFlag, + ppDefaultValue, pcchDefaultValue, pmdSetter, pmdGetter, rmdOtherMethod, cMax, + pcOtherMethod); +} + + + +extern "C" HRESULT +IMetaDataImport2_GetFieldProps(void *metadata, + mdFieldDef mb, + mdTypeDef *pClass, + LPWSTR szField, + ULONG cchField, + ULONG *pchField, + DWORD *pdwAttr, + PCCOR_SIGNATURE *ppvSigBlob, + ULONG *pcbSigBlob, + DWORD *pdwCPlusTypeFlag, + UVCP_CONSTANT *ppValue, + ULONG *pcchValue) { + auto meta = static_cast(metadata); + return meta->GetFieldProps(mb, pClass, szField, cchField, pchField, pdwAttr, ppvSigBlob, pcbSigBlob, + pdwCPlusTypeFlag, ppValue, pcchValue); +} + +extern "C" HRESULT +IMetaDataImport2_GetTypeDefProps(void *metadata, uint32_t mdTypeDef, LPWSTR szTypeDef, ULONG cchTypeDef, + ULONG *pchTypeDef, DWORD *pdwTypeDefFlags, mdToken *ptkExtends) { + auto meta = static_cast(metadata); + return meta->GetTypeDefProps(mdTypeDef, szTypeDef, cchTypeDef, pchTypeDef, pdwTypeDefFlags, ptkExtends); +} + +extern "C" HRESULT IMetaDataImport2_GetTypeDefPropsNameSize(void *metadata, uint32_t token, ULONG *pchTypeDef) { + auto meta = static_cast(metadata); + auto size = reinterpret_cast(&pchTypeDef); + return meta->GetTypeDefProps(token, 0, 0, size, 0, 0); +} + +extern "C" HRESULT IMetaDataImport2_EnumParams(void *metadata, HCORENUM *phEnum, + mdMethodDef mb, + mdParamDef *rParams, + ULONG cMax, + ULONG *pcTokens) { + auto meta = static_cast(metadata); + return meta->EnumParams(phEnum, mb, rParams, cMax, pcTokens); +} + +extern "C" void IMetaDataImport2_CloseEnum(void *metadata, HCORENUM phEnum) { + auto meta = static_cast(metadata); + meta->CloseEnum(phEnum); +} + + + +extern "C" HRESULT IMetaDataImport2_GetParamProps(void *metadata, + mdParamDef tk, + mdMethodDef *pmd, + ULONG *pulSequence, + LPWSTR szName, + ULONG cchName, + ULONG *pchName, + DWORD *pdwAttr, + DWORD *pdwCPlusTypeFlag, + UVCP_CONSTANT *ppValue, + ULONG *pcchValue) { + auto meta = static_cast(metadata); + return meta->GetParamProps(tk, pmd, pulSequence, szName, cchName, pchName, pdwAttr, pdwCPlusTypeFlag, ppValue, + pcchValue); +} + +extern "C" HRESULT IMetaDataImport2_GetCustomAttributeByName(void *metadata, + mdToken tkObj, + LPCWSTR szName, + const void **ppData, + ULONG *pcbData) { + auto meta = static_cast(metadata); + return meta->GetCustomAttributeByName(tkObj, szName, ppData, pcbData); +} + +extern "C" HRESULT IMetaDataImport2_EnumInterfaceImpls(void *meta, HCORENUM *phEnum, + mdTypeDef td, + mdInterfaceImpl *rImpls, + ULONG cMax, + ULONG *pcImpls) { + auto metadata = reinterpret_cast(meta); + return metadata->EnumInterfaceImpls(phEnum, td, rImpls, cMax, pcImpls); +} + +extern "C" HRESULT IMetaDataImport2_GetTypeRefProps(void *meta, mdTypeRef tr, + mdToken *ptkResolutionScope, + LPWSTR szName, + ULONG cchName, + ULONG *pchName) { + auto metadata = reinterpret_cast(meta); + return metadata->GetTypeRefProps(tr, ptkResolutionScope, szName, cchName, pchName); +} + +extern "C" HRESULT IMetaDataImport2_FindMethod(void *meta, mdTypeDef td, + LPCWSTR szName, + PCCOR_SIGNATURE pvSigBlob, + ULONG cbSigBlob, + mdMethodDef *pmb) { + auto metadata = reinterpret_cast(meta); + return metadata->FindMethod(td, szName, pvSigBlob, cbSigBlob, pmb); +} + +extern "C" HRESULT IMetaDataImport2_EnumGenericParams(void *meta, HCORENUM *phEnum, + mdToken tk, + mdGenericParam rGenericParams[], + ULONG cMax, + ULONG *pcGenericParams) { + auto metadata = reinterpret_cast(meta); + return metadata->EnumGenericParams(phEnum, tk, rGenericParams, cMax, pcGenericParams); +} + + +extern "C" HRESULT IMetaDataImport2_CountEnum(void *meta, HCORENUM hEnum, ULONG *pulCount) { + auto metadata = reinterpret_cast(meta); + return metadata->CountEnum(hEnum, pulCount); +} + +extern "C" HRESULT IMetaDataImport2_GetTypeSpecFromToken(void *meta, mdTypeSpec typespec, + PCCOR_SIGNATURE *ppvSig, + ULONG *pcbSig) { + auto metadata = reinterpret_cast(meta); + return metadata->GetTypeSpecFromToken(typespec, ppvSig, pcbSig); +} + + +extern "C" HRESULT IMetaDataImport2_EnumFields(void *meta, HCORENUM *phEnum, + mdTypeDef tkTypeDef, + mdFieldDef rgFields[], + ULONG cMax, + ULONG *pcTokens) { + auto metadata = reinterpret_cast(meta); + return metadata->EnumFields(phEnum, tkTypeDef, rgFields, cMax, pcTokens); +} + + +extern "C" HRESULT IMetaDataImport2_EnumMethodsWithName(void *meta, HCORENUM *phEnum, + mdTypeDef tkTypeDef, + LPCWSTR szName, + mdMethodDef rgMethods[], + ULONG cMax, + ULONG *pcTokens) { + auto metadata = reinterpret_cast(meta); + return metadata->EnumMethodsWithName(phEnum, tkTypeDef, szName, rgMethods, cMax, pcTokens); +} + +extern "C" HRESULT IMetaDataImport2_GetInterfaceImplProps(void *meta, mdInterfaceImpl tkInterfaceImpl, + mdTypeDef *ptkClass, + mdToken *ptkIface) { + auto metadata = reinterpret_cast(meta); + return metadata->GetInterfaceImplProps(tkInterfaceImpl, ptkClass, ptkIface); +} + +extern "C" HRESULT IMetaDataImport2_EnumMethods(void *meta, HCORENUM *phEnum, + mdTypeDef tkTypeDef, + mdMethodDef rgMethods[], + ULONG cMax, + ULONG *pcTokens) { + auto metadata = reinterpret_cast(meta); + return metadata->EnumMethods(phEnum, tkTypeDef, rgMethods, cMax, pcTokens); +} + + +extern "C" HRESULT IMetaDataImport2_EnumProperties(void *meta, HCORENUM *phEnum, + mdTypeDef tkTypDef, + mdProperty rgProperties[], + ULONG cMax, + ULONG *pcProperties) { + auto metadata = reinterpret_cast(meta); + return metadata->EnumProperties(phEnum, tkTypDef, rgProperties, cMax, pcProperties); +} + +extern "C" HRESULT IMetaDataImport2_EnumEvents(void *meta, HCORENUM *phEnum, + mdTypeDef tkTypDef, + mdEvent rgEvents[], + ULONG cMax, + ULONG *pcEvents) { + auto metadata = reinterpret_cast(meta); + return metadata->EnumEvents(phEnum, tkTypDef, rgEvents, cMax, pcEvents); +} + +extern "C" HRESULT IMetaDataImport2_GetEventProps(void *meta, mdEvent ev, + mdTypeDef *pClass, + LPCWSTR szEvent, + ULONG cchEvent, + ULONG *pchEvent, + DWORD *pdwEventFlags, + mdToken *ptkEventType, + mdMethodDef *pmdAddOn, + mdMethodDef *pmdRemoveOn, + mdMethodDef *pmdFire, + mdMethodDef rmdOtherMethod[], + ULONG cMax, + ULONG *pcOtherMethod) { + auto metadata = reinterpret_cast(meta); + return metadata->GetEventProps(ev, pClass, szEvent, cchEvent, pchEvent, pdwEventFlags, ptkEventType, pmdAddOn, + pmdRemoveOn, pmdFire, rmdOtherMethod, cMax, pcOtherMethod); +} + + + +extern "C" ULONG32 Enums_TypeFromToken(mdToken token) { + return TypeFromToken(token); +} + + +extern "C" ULONG Helpers_Get_Type_Name(void *meta, mdToken token, uint16_t *nameData, ULONG nameSize) { + auto metadata = reinterpret_cast(meta); + ULONG nameLength{0}; + auto data = reinterpret_cast(nameData); + + switch (TypeFromToken(token)) { + case CorTokenType::mdtTypeDef: { + metadata->GetTypeDefProps(token, data, nameSize, &nameLength, nullptr, nullptr); + break; + } + case CorTokenType::mdtTypeRef: { + metadata->GetTypeRefProps(token, nullptr, data, nameSize, &nameLength); + break; + } + default: + assert(false); + break; + } + + return nameLength - 1; +} + +extern "C" BOOL Helpers_IsTdPublic(DWORD value) { + return IsTdPublic(value); +} + +extern "C" BOOL Helpers_IsTdSpecialName(DWORD value) { + return IsTdSpecialName(value); +} + +extern "C" ULONG Helpers_CorSigUncompressCallingConv(PCCOR_SIGNATURE pData) { + return CorSigUncompressCallingConv(pData); +} + + +extern "C" ULONG Helpers_CorSigUncompressData(PCCOR_SIGNATURE pData) { + return CorSigUncompressData(pData); +} + +extern "C" CorElementType Helpers_CorSigUncompressElementType(PCCOR_SIGNATURE pData) { + return CorSigUncompressElementType(pData); +} + +extern "C" mdToken Helpers_CorSigUncompressToken(PCCOR_SIGNATURE pData) { + return CorSigUncompressToken(pData); +} + +extern "C" size_t Helpers_to_wstring(ULONG index, wchar_t *text) { + using namespace std; + auto str = to_wstring(index); + auto txt = std::wstring(text); + txt += str; + wcscpy(text, txt.c_str()); + return str.length() - 1; +} + +extern "C" BOOL Helpers_IsMdPublic(DWORD value) { + return IsMdPublic(value); +} + +extern "C" BOOL Helpers_IsMdFamily(DWORD value) { + return IsMdFamily(value); +} + +extern "C" BOOL Helpers_IsMdFamORAssem(DWORD value) { + return IsMdFamORAssem(value); +} + +extern "C" BOOL Helpers_IsMdSpecialName(DWORD value) { + return IsMdSpecialName(value); +} + +extern "C" BOOL Helpers_IsMdStatic(DWORD value) { + return IsMdStatic(value); +} + +extern "C" BOOL Helpers_IsMdFinal(DWORD value) { + return IsMdFinal(value); +} + +extern "C" BOOL Helpers_IsMdInstanceInitializerW(DWORD flags, const wchar_t *nameData) { + return IsMdInstanceInitializerW(flags, nameData); +} + +extern "C" BOOL Helpers_IsPrSpecialName(DWORD value) { + return IsPrSpecialName(value); +} + + +extern "C" void Helpers_bytesToGuid(uint8_t *data, GUID *iid) { + *iid = *reinterpret_cast(data); +} + +extern "C" PCWSTR Helpers_WindowsGetStringRawBuffer(HSTRING string, + UINT32 *length) { + return WindowsGetStringRawBuffer(string, length); +} + +extern "C" BOOL Helpers_IsTdInterface(DWORD value) { + return IsTdInterface(value); +} + +extern "C" BOOL Helpers_IsTdClass(DWORD value) { + return IsTdClass(value); +} + +extern "C" BOOL Helpers_IsEvSpecialName(DWORD value) { + return IsEvSpecialName(value); +} + + + + +/* +extern "C" HRESULT GenericInstanceIdBuilder_locatorImpl(PCWSTR name, IRoSimpleMetaDataBuilder & builder) { + shared_ptr declaration{ metadataReader.findByName(name) }; + ASSERT(declaration); + + DeclarationKind kind{ declaration->kind() }; + switch (kind) { + case DeclarationKind::Class: { + ClassDeclaration* classDeclaration{ static_cast(declaration.get()) }; + const InterfaceDeclaration& defaultInterface{ classDeclaration->defaultInterface() }; + IID defaultInterfaceId = defaultInterface.id(); + ASSERT_SUCCESS(builder.SetRuntimeClassSimpleDefault(name, defaultInterface.fullName().data(), &defaultInterfaceId)); + return S_OK; + } + + case DeclarationKind::Interface: { + InterfaceDeclaration* interfaceDeclaration{ static_cast(declaration.get()) }; + ASSERT_SUCCESS(builder.SetWinRtInterface(interfaceDeclaration->id())); + return S_OK; + } + + case DeclarationKind::GenericInterface: { + GenericInterfaceDeclaration* genericInterfaceDeclaration{ static_cast(declaration.get()) }; + ASSERT_SUCCESS(builder.SetParameterizedInterface(genericInterfaceDeclaration->id(), genericInterfaceDeclaration->number_of_generic_parameters())); + return S_OK; + } + + case DeclarationKind::Enum: { + EnumDeclaration* enumDeclaration{ static_cast(declaration.get()) }; + ASSERT_SUCCESS(builder.SetEnum(enumDeclaration->fullName().data(), Signature::toString(nullptr, enumDeclaration->type()).data())); + return S_OK; + } + + case DeclarationKind::Struct: { + StructDeclaration* structDeclaration{ static_cast(declaration.get()) }; + + vector fieldNames; + for (const StructFieldDeclaration& field : *structDeclaration) { + fieldNames.push_back(Signature::toString(field._metadata.Get(), field.type())); + } + + vector fieldNamesW; + for (wstring& fieldName : fieldNames) { + fieldNamesW.push_back(const_cast(fieldName.data())); + } + + ASSERT_SUCCESS(builder.SetStruct(structDeclaration->fullName().data(), structDeclaration->size(), fieldNamesW.data())); + return S_OK; + } + + case DeclarationKind::Delegate: { + DelegateDeclaration* delegateDeclaration{ static_cast(declaration.get()) }; + ASSERT_SUCCESS(builder.SetDelegate(delegateDeclaration->id())); + return S_OK; + } + + case DeclarationKind::GenericDelegate: { + GenericDelegateDeclaration* genericDelegateDeclaration{ static_cast(declaration.get()) }; + ASSERT_SUCCESS(builder.SetParameterizedDelegate(genericDelegateDeclaration->id(), genericDelegateDeclaration->number_of_generic_parameters())); + return S_OK; + } + + default: + ASSERT_NOT_REACHED(); + } +} + + +extern "C" void GenericInstanceIdBuilder_generateId(wchar_t * fullName, GUID * iid) { + wstring declarationFullName = std::wstring(fullName); + + HSTRING* nameParts{ nullptr }; + DWORD namePartsCount{ 0 }; + ASSERT_SUCCESS(RoParseTypeName(HStringReference(declarationFullName.data()).Get(), &namePartsCount, &nameParts)); + + array namePartsW; + ASSERT(namePartsCount < namePartsW.size()); + + for (size_t i = 0; i < namePartsCount; ++i) { + namePartsW[i] = WindowsGetStringRawBuffer(nameParts[i], nullptr); + } + + + ASSERT_SUCCESS(ro_get_parameterized_type_instance_iid(namePartsCount, namePartsW.data(), Ro::Locator(&GenericInstanceIdBuilder_locatorImpl), &guid, nullptr)); + + for (size_t i = 0; i < namePartsCount; ++i) { + ASSERT_SUCCESS(WindowsDeleteString(nameParts[i])); + } + + CoTaskMemFree(nameParts); + + return guid; +} + +*/ + +extern "C" HRESULT Helpers_RO_E_METADATA_NAME_IS_NAMESPACE = RO_E_METADATA_NAME_IS_NAMESPACE; + +extern "C" mdToken Helpers_mdTokenNil = mdTokenNil; +extern "C" mdToken Helpers_mdModuleNil = mdModuleNil; +extern "C" mdToken Helpers_mdTypeRefNil = mdTypeRefNil; +extern "C" mdToken Helpers_mdTypeDefNil = mdTypeDefNil; +extern "C" mdToken Helpers_mdFieldDefNil = mdFieldDefNil; +extern "C" mdToken Helpers_mdMethodDefNil = mdMethodDefNil; +extern "C" mdToken Helpers_mdParamDefNil = mdParamDefNil; +extern "C" mdToken Helpers_mdInterfaceImplNil = mdInterfaceImplNil; +extern "C" mdToken Helpers_mdMemberRefNil = mdMemberRefNil; +extern "C" mdToken Helpers_mdCustomAttributeNil = mdCustomAttributeNil; +extern "C" mdToken Helpers_mdPermissionNil = mdPermissionNil; +extern "C" mdToken Helpers_mdSignatureNil = mdSignatureNil; +extern "C" mdToken Helpers_mdEventNil = mdEventNil; +extern "C" mdToken Helpers_mdPropertyNil = mdPropertyNil; +extern "C" mdToken Helpers_mdModuleRefNil = mdModuleRefNil; +extern "C" mdToken Helpers_mdTypeSpecNil = mdTypeSpecNil; +extern "C" mdToken Helpers_mdAssemblyNil = mdAssemblyNil; +extern "C" mdToken Helpers_mdAssemblyRefNil = mdAssemblyRefNil; +extern "C" mdToken Helpers_mdFileNil = mdFileNil; +extern "C" mdToken Helpers_mdExportedTypeNil = mdExportedTypeNil; +extern "C" mdToken Helpers_mdManifestResourceNil = mdManifestResourceNil; + +extern "C" mdToken Helpers_mdGenericParamNil = mdGenericParamNil; +extern "C" mdToken Helpers_mdGenericParamConstraintNil = mdGenericParamConstraintNil; +extern "C" mdToken Helpers_mdMethodSpecNil = mdMethodSpecNil; + +extern "C" mdToken Helpers_mdStringNil = mdStringNil; \ No newline at end of file diff --git a/core/src/headers.h b/core-bindings/src/headers.h old mode 100755 new mode 100644 similarity index 71% rename from core/src/headers.h rename to core-bindings/src/headers.h index 0c326f1..2e7d32a --- a/core/src/headers.h +++ b/core-bindings/src/headers.h @@ -1,10 +1,15 @@ -#include -#include -# define NDEBUG -#include -#include -#include -#include -#include -const size_t MAX_IDENTIFIER_LENGTH{ 511 }; -using identifier = std::array; \ No newline at end of file +#include +#include +#include +# define NDEBUG +#include +#include +#include +#include +#include +#include +#include +const size_t MAX_IDENTIFIER_LENGTH{ 511 }; +using identifier = std::array; + +typedef struct _locator Locator; \ No newline at end of file diff --git a/core-bindings/src/lib.rs b/core-bindings/src/lib.rs new file mode 100644 index 0000000..02f8704 --- /dev/null +++ b/core-bindings/src/lib.rs @@ -0,0 +1,26 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +windows::include_bindings!(); + + +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + + +impl GUID { + pub fn new() -> Self { + Self { + Data1: 0, + Data2: 0, + Data3: 0, + Data4: [0_u8;8] + } + } +} + +impl Default for GUID { + fn default() -> Self { + Self::new() + } +} \ No newline at end of file diff --git a/core/Cargo.toml b/core/Cargo.toml index 59ba23d..44d14a6 100755 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -2,7 +2,6 @@ name = "core" version = "0.1.0" edition = "2018" -build = "build.rs" [lib] name = "nativescript" @@ -12,11 +11,7 @@ crate-type = ["dylib"] [dependencies] windows = "0.10.0" rusty_v8 = "0.21.0" -bindings = { package = "core_bindings", path = "bindings" } +core_bindings = { package = "core_bindings", path = "../core-bindings" } chrono = "0.4.19" libc = "0.2.95" - -[build-dependencies] -windows = "0.10.0" -cc = "1.0" -bindgen = "0.53.1" +lazy_static = "1.4.0" diff --git a/core/bindings/build.rs b/core/bindings/build.rs deleted file mode 100755 index 1c54dd8..0000000 --- a/core/bindings/build.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn main() { - windows::build!( - Windows::Win32::System::Console::WriteConsoleA, - Windows::Win32::System::WindowsProgramming::STD_OUTPUT_HANDLE, - Windows::Win32::System::WindowsProgramming::GetStdHandle, - Windows::Win32::System::SystemServices::GetProcAddress, - Windows::Win32::System::SystemServices::LoadLibraryA, - Windows::Win32::System::SystemServices::FARPROC - ); -} \ No newline at end of file diff --git a/core/bindings/src/lib.rs b/core/bindings/src/lib.rs deleted file mode 100755 index 7e2815a..0000000 --- a/core/bindings/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ -windows::include_bindings!(); \ No newline at end of file diff --git a/core/build.rs b/core/build.rs deleted file mode 100755 index 884ae12..0000000 --- a/core/build.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::env; - -use std::path::PathBuf; - -fn main() { - let mut build = cc::Build::default() ; - build.file("src/bindings.cpp") - .cpp(true) - .include("C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.8\\Include\\um") - .static_crt(true) - .compile("libcorebindings"); - - println!("cargo:rerun-if-changed=src/bindings.cpp"); - - -/* - let bindgen = bindgen::builder() - .clang_args(&["-I", "C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.8\\Include\\um"]) - .header("src/bindings.cpp") - // Tell cargo to invalidate the built crate whenever any of the - // included header files changed. - .parse_callbacks(Box::new(bindgen::CargoCallbacks)) - // Finish the builder and generate the bindings. - .generate() - // Unwrap the Result and panic on failure. - .expect("Unable to generate bindings"); - - // Write the bindings to the $OUT_DIR/bindings.rs file. - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - bindgen - .write_to_file(out_path.join("bindings.rs")) - .expect("Couldn't write bindings!");*/ -} \ No newline at end of file diff --git a/core/src/bindings.cpp b/core/src/bindings.cpp deleted file mode 100755 index 8bc54dc..0000000 --- a/core/src/bindings.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include "headers.h" - - -typedef HRESULT (__cdecl * ProcRoGetMetaDataFile)(const HSTRING name, IMetaDataDispenserEx *, HSTRING *, IMetaDataImport2 **, mdTypeDef *typeDefToken); - - -extern "C" HRESULT Rometadataresolution_RoGetMetaDataFile(const HSTRING name, void* metaDataDispenser, void* metaDataFilePath, void** metaDataImport, mdTypeDef *typeDefToken){ - auto dispenser = reinterpret_cast(metaDataDispenser); - auto filePath = reinterpret_cast(metaDataFilePath); - auto import = (IMetaDataImport2 **)(metaDataImport); - - auto proc = (ProcRoGetMetaDataFile)GetProcAddress( - LoadLibraryA("api-ms-win-ro-typeresolution-l1-1-0.dll"), - "RoGetMetaDataFile" - ); - - return proc(name, dispenser, filePath, import, typeDefToken); -} - -extern "C" void IMetaDataImport2_GetTypeDefProps(void* metadata, uint32_t mdTypeDef, void* szTypeDef, ULONG cchTypeDef, ULONG * pchTypeDef , DWORD * pdwTypeDefFlags, mdToken * ptkExtends) { - auto meta = static_cast(metadata); - auto data = reinterpret_cast(szTypeDef); - meta->GetTypeDefProps(mdTypeDef, data, cchTypeDef, pchTypeDef, pdwTypeDefFlags, ptkExtends); -} - -extern "C" void IMetaDataImport2_GetTypeDefPropsNameSize(void* metadata, uint32_t token, ULONG * pchTypeDef) { - auto meta = static_cast(metadata); - auto size = reinterpret_cast(&pchTypeDef); - auto result = meta->GetTypeDefProps(token, 0, 0, size, 0, 0); -} - - -extern "C" void IMetaDataImport2_EnumInterfaceImpls(void* meta, mdToken token) { - auto metadata = reinterpret_cast(meta); - HCORENUM enumerator{ nullptr }; - ULONG count{ 0 }; - std::array tokens; - assert(metadata->EnumInterfaceImpls(&enumerator, token, tokens.data(), tokens.size(), &count)); - assert(count < tokens.size() - 1); - metadata->CloseEnum(enumerator); - std::cout << "count " << count << "\n"; - - //vector> result; - for (size_t i = 0; i < count; ++i) { - mdToken interfaceToken{ mdTokenNil }; - assert(metadata->GetInterfaceImplProps(tokens[i], nullptr, &interfaceToken)); - - //result.push_back(DeclarationFactory::makeInterfaceDeclaration(metadata, interfaceToken)); - } - - - // return result; - - -} - - -extern "C" ULONG32 Enums_TypeFromToken(mdToken token) { - return TypeFromToken(token); -} - - -extern "C" ULONG Helpers_Get_Type_Name(void* meta , mdToken token,uint16_t * nameData, size_t nameSize) { - auto metadata = reinterpret_cast(meta); - ULONG nameLength{ 0 }; - auto data = reinterpret_cast(nameData); - - switch (TypeFromToken(token)) { - case CorTokenType::mdtTypeDef: { - metadata->GetTypeDefProps(token, data, nameSize, &nameLength, nullptr, nullptr); - break; - } - case CorTokenType::mdtTypeRef: { - metadata->GetTypeRefProps(token, nullptr, data, nameSize, &nameLength); - break; - } - default: - assert(); - break; - } - - return nameLength - 1; -} - -extern "C" BOOL Helpers_IsTdPublic(DWORD value){ - return IsTdPublic(value); -} - -extern "C" BOOL Helpers_IsTdSpecialName(DWORD value){ - return IsTdSpecialName(value); -} \ No newline at end of file diff --git a/core/src/bindings.rs b/core/src/bindings.rs index 2d70f58..ec826a2 100644 --- a/core/src/bindings.rs +++ b/core/src/bindings.rs @@ -1,60 +1,617 @@ -use prelude::*; +use crate::prelude::*; -extern { - fn Rometadataresolution_RoGetMetaDataFile( - name: windows::HSTRING, meta_data_dispenser: *const c_void, meta_data_file_path: *const c_void, meta_data_import: *mut *mut c_void, type_def_token: *mut u32, - ) -> c_long; +pub mod rometadataresolution { + use crate::prelude::*; + use windows::{HRESULT, HSTRING}; - fn IMetaDataImport2_GetTypeDefProps(metadata: *const c_void, md_type_def: c_uint, sz_type_def: *mut c_void, cch_type_def: i64, pch_type_def: *mut i64, pdw_type_def_flags: *mut i64, md_token: *mut u32) -> windows::HRESULT; + pub(crate) fn ro_get_meta_data_file( + name: &mut windows::HSTRING, meta_data_dispenser: Option<*mut c_void>, meta_data_file_path: Option<*mut c_void>, meta_data_import: Option<*mut *mut c_void>, type_def_token: Option<*mut u32>, + ) -> HRESULT { + unsafe { + windows::HRESULT(core_bindings::Rometadataresolution_RoGetMetaDataFile( + name, meta_data_dispenser.unwrap_or(0 as _), meta_data_file_path.unwrap_or(0 as _), meta_data_import.unwrap_or(0 as _), type_def_token.unwrap_or(0 as _), + ) as u32) + } + } - fn IMetaDataImport2_GetTypeDefPropsNameSize(metadata: *const c_void, md_type_def: c_uint, pch_type_def: *mut i64); + pub(crate) fn ro_parse_type_name( + type_name: HSTRING, + parts_count: *mut DWORD, + type_name_parts: *mut *mut HSTRING, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::Rometadataresolution_RoParseTypeName( + type_name, + parts_count, + type_name_parts, + ) as u32 + ) + } + } - fn IMetaDataImport2_EnumInterfaceImpls(metadata: *const c_void, md_type_def: c_uint); - fn Enums_TypeFromToken(token: mdToken) -> ULONG; + pub(crate) fn ro_get_parameterized_type_instance_iid( + name_element_count: UINT32, + name_elements: *mut PCWSTR, + meta_data_locator: *const IRoMetaDataLocator, + iid: *mut GUID, + p_extra: Option<*mut ROPARAMIIDHANDLE>, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::Rometadataresolution_RoGetParameterizedTypeInstanceIID( + name_element_count, + name_elements, + meta_data_locator, + iid, + p_extra.unwrap_or(0 as _), + ) as u32 + ) + } + } - fn Helpers_Get_Type_Name(meta: *const c_void, md_token: mdToken, name: *mut libc::wchar_t, size: usize) -> ULONG; + pub(crate) fn ro_locator(fn_: ::core::option::Option< + unsafe extern "C" fn(name: PCWSTR, builder: *mut IRoSimpleMetaDataBuilder) -> HRESULT, + >) -> Ro_detail__Locator< + ::core::option::Option< + unsafe extern "C" fn(arg1: PCWSTR, arg2: *mut IRoSimpleMetaDataBuilder) -> HRESULT, + >, + > { + unsafe { + core_bindings::Rometadataresolution_Ro_Locator(fn_) + } + } +} - fn Helpers_IsTdPublic(value: DWORD) -> bool; +pub mod imeta_data_import2 { + use crate::prelude::*; + use core_bindings::*; + use windows::HRESULT; - fn Helpers_IsTdSpecialName(value: DWORD) -> bool; -} + pub(crate) fn get_type_def_props(metadata: *mut c_void, md_type_def: c_uint, sz_type_def: Option, cch_type_def: Option, pch_type_def: Option<*mut ULONG>, pdw_type_def_flags: Option<*mut ULONG>, md_token: Option<*mut ULONG32>) -> HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_GetTypeDefProps(metadata, md_type_def, sz_type_def.unwrap_or(0 as _), cch_type_def.unwrap_or(0), pch_type_def.unwrap_or(&mut 0), pdw_type_def_flags.unwrap_or(0 as _), md_token.unwrap_or(&mut 0)) as u32) + } + //unsafe { IMetaDataImport2_GetTypeDefProps(metadata, md_type_def, sz_type_def.unwrap_or(std::ptr::null_mut()), cch_type_def.unwrap_or(0), pch_type_def.unwrap_or(&mut 0), pdw_type_def_flags, md_token.unwrap_or(&mut 0)) } + } -pub mod rometadataresolution { - fn ro_get_meta_data_file( - name: windows::HSTRING, meta_data_dispenser: *const c_void, meta_data_file_path: *const c_void, meta_data_import: *mut *mut c_void, type_def_token: *mut u32, - ) -> c_long { - Rometadataresolution_RoGetMetaDataFile(name, meta_data_dispenser, meta_data_file_path, meta_data_import, type_def_token) - } -} + fn get_type_def_props_name_size(metadata: *mut c_void, md_type_def: c_uint, pch_type_def: *mut ULONG) -> HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_GetTypeDefPropsNameSize(metadata, md_type_def, pch_type_def) as u32) + } + //unsafe { IMetaDataImport2_GetTypeDefPropsNameSize(metadata, md_type_def, pch_type_def) } + } -pub mod imeta_data_import2 { - fn get_type_def_props(metadata: *const c_void, md_type_def: c_uint, sz_type_def: *mut c_void, cch_type_def: i64, pch_type_def: *mut i64, pdw_type_def_flags: *mut i64, md_token: *mut u32) { - IMetaDataImport2_GetTypeDefProps(metadata, md_type_def, sz_type_def, cch_type_def, pch_type_def, pdw_type_def_flags, md_token) - } + pub(crate) fn get_field_props(metadata: *mut c_void, + mb: MdFieldDef, + p_class: Option<*mut mdTypeDef>, + sz_field: Option<*mut u16>, + cch_field: Option, + pch_field: Option<*mut ULONG>, + pdw_attr: Option<*mut DWORD>, + ppv_sig_blob: Option<*mut PCCOR_SIGNATURE>, + pcb_sig_blob: Option<*mut ULONG>, + pdw_cplus_type_flag: Option<*mut DWORD>, + pp_value: Option<*mut UVCP_CONSTANT>, + pcch_value: Option<*mut ULONG>) -> windows::HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_GetFieldProps(metadata, + mb, + p_class.unwrap_or(0 as _), + sz_field.unwrap_or(0 as _), + cch_field.unwrap_or_default(), + pch_field.unwrap_or(0 as _), + pdw_attr.unwrap_or(0 as _), + ppv_sig_blob.unwrap_or(0 as _), + pcb_sig_blob.unwrap_or(0 as _), + pdw_cplus_type_flag.unwrap_or(0 as _), + pp_value.unwrap_or(0 as _), + pcch_value.unwrap_or(0 as _)) as u32) + } + } + + pub(crate) fn get_property_props(metadata: *mut c_void, prop: mdProperty, p_class: Option<*mut mdTypeDef>, + sz_property: Option<*mut u16>, + cch_property: Option, + pch_property: Option<*mut ULONG>, + pdw_prop_flags: Option<*mut DWORD>, + ppv_sig: Option<*mut PCCOR_SIGNATURE>, + pb_sig: Option<*mut ULONG>, + pdw_cplus_type_flag: Option<*mut DWORD>, + pp_default_value: Option<*mut UVCP_CONSTANT>, + pcch_default_value: Option<*mut ULONG>, + pmd_setter: Option<*mut mdMethodDef>, + pmd_getter: Option<*mut mdMethodDef>, + rmd_other_method: Option<*mut mdMethodDef>, + c_max: Option, + pc_other_method: Option<*mut ULONG>) -> windows::HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_GetPropertyProps( + metadata, prop, + p_class.unwrap_or(0 as _), + sz_property.unwrap_or(0 as _), + cch_property.unwrap_or_default(), + pch_property.unwrap_or(0 as _), + pdw_prop_flags.unwrap_or(0 as _), + ppv_sig.unwrap_or(0 as _), + pb_sig.unwrap_or(0 as _), + pdw_cplus_type_flag.unwrap_or(0 as _), + pp_default_value.unwrap_or(0 as _), + pcch_default_value.unwrap_or(0 as _), + pmd_setter.unwrap_or(0 as _), + pmd_getter.unwrap_or(0 as _), + rmd_other_method.unwrap_or(0 as _), + c_max.unwrap_or_default(), + pc_other_method.unwrap_or(0 as _), + ) as u32) + } + } + + pub(crate) fn get_method_props(metadata: *mut c_void, + tk_method_def: mdMethodDef, + ptk_class: Option<*mut mdTypeDef>, + sz_method: Option<*mut u16>, + cch_method: Option, + pch_method: Option<*mut ULONG>, + pdw_attr: Option<*mut DWORD>, + ppv_sig_blob: Option<*mut PCCOR_SIGNATURE>, + pcb_sig_blob: Option<*mut ULONG>, + pul_code_rva: Option<*mut ULONG>, + pdw_impl_flags: Option<*mut DWORD>) -> windows::HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_GetMethodProps( + metadata, tk_method_def, + ptk_class.unwrap_or(0 as _), sz_method.unwrap_or(0 as _), + cch_method.unwrap_or_default(), pch_method.unwrap_or(0 as _), + pdw_attr.unwrap_or(0 as _), ppv_sig_blob.unwrap_or(0 as _), + pcb_sig_blob.unwrap_or(0 as _), pul_code_rva.unwrap_or(0 as _), + pdw_impl_flags.unwrap_or(0 as _), + ) as u32) + } + } + + + pub(crate) fn enum_params(metadata: *mut c_void, ph_enum: *mut HCORENUM, mb: MdMethodDef, r_params: *mut MdParamDef, c_max: ULONG, + pc_tokens: *mut ULONG) -> windows::HRESULT { + unsafe { HRESULT(core_bindings::IMetaDataImport2_EnumParams(metadata, ph_enum, mb, r_params, c_max, pc_tokens) as u32) } + } + + pub(crate) fn close_enum(metadata: *mut c_void, ph_enum: HCORENUM) { + unsafe { + core_bindings::IMetaDataImport2_CloseEnum(metadata, ph_enum) + } + } + + pub(crate) fn get_param_props(metadata: *mut c_void, tk: mdParamDef, + pmd: Option<*mut mdMethodDef>, + pul_sequence: Option<*mut ULONG>, + sz_name: Option<*mut u16>, + cch_name: Option, + pch_name: Option<*mut ULONG>, + pdw_attr: Option<*mut DWORD>, + pdw_cplus_type_flag: Option<*mut DWORD>, + pp_value: Option<*mut UVCP_CONSTANT>, + pcch_value: Option<*mut ULONG>) -> windows::HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_GetParamProps(metadata, tk, + pmd.unwrap_or(0 as _), + pul_sequence.unwrap_or(0 as _), + sz_name.unwrap_or(0 as _), + cch_name.unwrap_or_default(), + pch_name.unwrap_or(0 as _), + pdw_attr.unwrap_or(0 as _), + pdw_cplus_type_flag.unwrap_or(0 as _), + pp_value.unwrap_or(0 as _), + pcch_value.unwrap_or(0 as _)) as u32 + ) + } + } + + pub(crate) fn get_custom_attribute_by_name(metadata: *mut c_void, + tk_obj: mdToken, + sz_name: Option<*const u16>, + pp_data: Option<*mut *const ::core::ffi::c_void>, + pcb_data: Option<*mut ULONG>) -> windows::HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_GetCustomAttributeByName(metadata, + tk_obj, + sz_name.unwrap_or(0 as _), + pp_data.unwrap_or(0 as _), + pcb_data.unwrap_or(0 as _)) as u32) + } + } + + pub(crate) fn enum_interface_impls(metadata: *mut c_void, ph_enum: *mut HCORENUM, + td: Option, + r_impls: Option<*mut mdInterfaceImpl>, + c_max: Option, + pc_impls: Option<*mut ULONG>) -> windows::HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_EnumInterfaceImpls(metadata, ph_enum, + td.unwrap_or_default(), + r_impls.unwrap_or(0 as _), + c_max.unwrap_or(0 as _), + pc_impls.unwrap_or(0 as _)) as u32) + } + } + + pub(crate) fn get_type_ref_props(meta: *mut c_void, tr: mdTypeRef, + ptk_resolution_scope: Option<*mut mdToken>, + sz_name: Option<*mut u16>, + cch_name: Option, + pch_name: Option<*mut ULONG>) -> windows::HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_GetTypeRefProps(meta, tr, + ptk_resolution_scope.unwrap_or(0 as _), + sz_name.unwrap_or(0 as _), + cch_name.unwrap_or_default(), + pch_name.unwrap_or(0 as _)) as u32 + ) + } + } + + pub(crate) fn find_method(meta: *mut c_void, + td: mdTypeDef, + sz_name: LPCWSTR, + pv_sig_blob: Option, + cb_sig_blob: ULONG, + pmb: *mut mdMethodDef) -> windows::HRESULT { + unsafe { + HRESULT( + IMetaDataImport2_FindMethod(meta, td, sz_name, pv_sig_blob.unwrap_or(0 as _), cb_sig_blob, pmb) as u32 + ) + } + } + + pub(crate) fn enum_generic_params( + meta: *mut c_void, + ph_enum: *mut HCORENUM, + tk: mdToken, + r_generic_params: Option<*mut mdGenericParam>, + c_max: Option, + pc_generic_params: Option<*mut ULONG>, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_EnumGenericParams( + meta, + ph_enum, + tk, + r_generic_params.unwrap_or(0 as _), + c_max.unwrap_or_default(), + pc_generic_params.unwrap_or(0 as _), + ) as u32 + ) + } + } + + + pub fn count_enum( + meta: *mut c_void, + h_enum: HCORENUM, + pul_count: *mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_CountEnum(meta, h_enum, pul_count) as u32 + ) + } + } + + pub fn get_type_spec_from_token( + meta: *mut c_void, + typespec: mdTypeSpec, + ppv_sig: *mut PCCOR_SIGNATURE, + pcb_sig: *mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT( + IMetaDataImport2_GetTypeSpecFromToken( + meta, + typespec, + ppv_sig, + pcb_sig, + ) as u32 + ) + } + } + + + pub(crate) fn enum_fields( + meta: *mut c_void, + ph_enum: *mut HCORENUM, + tk_type_def: mdTypeDef, + rg_fields: *mut mdFieldDef, + c_max: ULONG, + pc_tokens: *mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_EnumFields( + meta, + ph_enum, + tk_type_def, + rg_fields, + c_max, + pc_tokens, + ) as u32 + ) + } + } + + pub(crate) fn enum_methods_with_name( + meta: *mut c_void, + ph_enum: *mut HCORENUM, + tk_type_def: mdTypeDef, + sz_name: LPCWSTR, + rg_methods: *mut mdMethodDef, + c_max: ULONG, + pc_tokens: *mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_EnumMethodsWithName( + meta, + ph_enum, + tk_type_def, + sz_name, + rg_methods, + c_max, + pc_tokens, + ) as u32 + ) + } + } + + pub(crate) fn get_interface_impl_props( + meta: *mut ::core::ffi::c_void, + tk_interface_impl: mdInterfaceImpl, + ptk_class: Option<*mut mdTypeDef>, + ptk_iface: Option<*mut mdToken>, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_GetInterfaceImplProps( + meta, + tk_interface_impl, + ptk_class.unwrap_or(0 as _), + ptk_iface.unwrap_or(0 as _), + ) as u32 + ) + } + } + + pub(crate) fn enum_methods( + meta: *mut c_void, + ph_enum: *mut HCORENUM, + tk_type_def: mdTypeDef, + rg_methods: *mut mdMethodDef, + c_max: ULONG, + pc_tokens: *mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_EnumMethods( + meta, + ph_enum, + tk_type_def, + rg_methods, + c_max, + pc_tokens, + ) as u32 + ) + } + } + + pub(crate) fn enum_properties( + meta: *mut c_void, + ph_enum: *mut HCORENUM, + tk_typ_def: mdTypeDef, + rg_properties: *mut mdProperty, + c_max: ULONG, + pc_properties: *mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_EnumProperties( + meta, + ph_enum, + tk_typ_def, + rg_properties, + c_max, + pc_properties, + ) as u32 + ) + } + } - fn get_type_def_props_name_size(metadata: *const c_void, md_type_def: c_uint, pch_type_def: *mut i64) { - IMetaDataImport2_GetTypeDefPropsNameSize(metadata, md_type_def, pch_type_def) - } + pub fn enum_events( + meta: *mut c_void, + ph_enum: *mut HCORENUM, + tk_typ_def: mdTypeDef, + rg_events: *mut mdEvent, + c_max: ULONG, + pc_events: *mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_EnumEvents( + meta, + ph_enum, + tk_typ_def, + rg_events, + c_max, + pc_events, + ) as u32 + ) + } + } + + pub(crate) fn get_event_props( + meta: *mut c_void, + ev: mdEvent, + p_class: Option<*mut mdTypeDef>, + sz_event: Option, + cch_event: Option, + pch_event: Option<*mut ULONG>, + pdw_event_flags: Option<*mut DWORD>, + ptk_event_type: Option<*mut mdToken>, + pmd_add_on: Option<*mut mdMethodDef>, + pmd_remove_on: Option<*mut mdMethodDef>, + pmd_fire: Option<*mut mdMethodDef>, + rmd_other_method: Option<*mut mdMethodDef>, + c_max: Option, + pc_other_method: Option<*mut ULONG>, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_GetEventProps( + meta: *mut ::core::ffi::c_void, + ev: mdEvent, + p_class: *mut mdTypeDef, + sz_event: LPCWSTR, + cch_event: ULONG, + pch_event: *mut ULONG, + pdw_event_flags: *mut DWORD, + ptk_event_type: *mut mdToken, + pmd_add_on: *mut mdMethodDef, + pmd_remove_on: *mut mdMethodDef, + pmd_fire: *mut mdMethodDef, + rmd_other_method: *mut mdMethodDef, + c_max: ULONG, + pc_other_method: *mut ULONG, + ) as u32 + ) + } + } } pub mod enums { - fn type_from_token(token: mdToken) -> ULONG { - Enums_TypeFromToken(token) - } + use crate::prelude::*; + + pub(crate) fn type_from_token(token: mdToken) -> ULONG { + unsafe { core_bindings::Enums_TypeFromToken(token) } + } } pub mod helpers { - fn get_type_name(meta: *const c_void, md_token: mdToken, name: *mut libc::wchar_t, size: usize) -> ULONG { - Helpers_Get_Type_Name(meta, md_token, name, size) - } - - fn is_td_public(value: DWORD) -> bool { - Helpers_IsTdPublic(value) - } - - fn is_td_special_name(value: DWORD) -> bool { - Helpers_IsTdSpecialName(value) - } -} \ No newline at end of file + use crate::prelude::*; + use core_bindings::PCCOR_SIGNATURE; + use windows::HSTRING; + + pub(crate) fn get_type_name(meta: *mut c_void, md_token: mdToken, name: *mut libc::wchar_t, size: ULONG) -> ULONG { + unsafe { core_bindings::Helpers_Get_Type_Name(meta, md_token, name, size) } + } + + pub(crate) fn is_td_public(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsTdPublic(value) == 1 } + } + + pub(crate) fn is_td_special_name(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsTdSpecialName(value) == 1 } + } + + pub(crate) fn cor_sig_uncompress_calling_conv(p_data: PCCOR_SIGNATURE) -> ULONG { + unsafe { + core_bindings::Helpers_CorSigUncompressCallingConv(p_data) + } + } + + pub(crate) fn cor_sig_uncompress_data(p_data: PCCOR_SIGNATURE) -> ULONG { + unsafe { core_bindings::Helpers_CorSigUncompressData(p_data) } + } + + pub(crate) fn cor_sig_uncompress_element_type(p_data: PCCOR_SIGNATURE) -> crate::enums::CorElementType { + unsafe { + core_bindings::Helpers_CorSigUncompressElementType(p_data).into() + } + } + + pub(crate) fn cor_sig_uncompress_token(p_data: PCCOR_SIGNATURE) -> MdToken { + unsafe { + core_bindings::Helpers_CorSigUncompressToken(p_data) + } + } + + pub(crate) fn to_wstring(index: ULONG, text: *mut u16) -> usize { + unsafe { + core_bindings::Helpers_to_wstring(index, text) + } + } + + pub(crate) fn is_md_public(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsMdPublic(value) == 1 } + } + + pub(crate) fn is_md_family(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsMdFamily(value) == 1 } + } + + pub(crate) fn is_md_fam_orassem(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsMdFamORAssem(value) == 1 } + } + + pub(crate) fn is_md_special_name(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsMdSpecialName(value) == 1 } + } + + pub(crate) fn is_md_static(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsMdStatic(value) == 1 } + } + + pub(crate) fn is_md_final(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsMdFinal(value) == 1 } + } + + pub(crate) fn is_md_instance_initializer_w(flags: DWORD, name_data: *const u16) -> bool { + unsafe { + core_bindings::Helpers_IsMdInstanceInitializerW(flags, name_data) == 1 + } + } + + pub(crate) fn is_pr_special_name(value: DWORD) -> bool { + unsafe { + core_bindings::Helpers_IsPrSpecialName(value) == 1 + } + } + + pub(crate) fn bytes_to_guid( + data: *mut u8, + guid: *mut GUID, + ) { + unsafe { + core_bindings::Helpers_bytesToGuid(data, guid) + } + } + + pub(crate) fn windows_get_string_raw_buffer(string: HSTRING, length: Option<*mut UINT32>) -> PCWSTR { + unsafe { + core_bindings::Helpers_WindowsGetStringRawBuffer(string: HSTRING, length.unwrap_or(0 as _)) + } + } + + pub(crate) fn is_td_interface(value: DWORD) -> bool { + unsafe { + core_bindings::Helpers_IsTdInterface(value: DWORD) == 1 + } + } + + pub(crate) fn is_td_class(value: DWORD) -> bool { + unsafe { + core_bindings::Helpers_IsTdClass(value: DWORD) == 1 + } + } + + pub fn is_ev_special_name(value: DWORD) -> bool { + unsafe { + core_bindings::Helpers_IsEvSpecialName(value) == 1 + } + } +} + + + diff --git a/core/src/enums.rs b/core/src/enums.rs new file mode 100644 index 0000000..73f934c --- /dev/null +++ b/core/src/enums.rs @@ -0,0 +1,211 @@ +use std::convert::TryFrom; + +#[derive(Copy, Clone, PartialEq, Debug)] +#[repr(C)] +pub enum CorCallingConvention +{ + ImageCeeCsCallconvDefault = 0x0, + + ImageCeeCsCallconvVararg = 0x5, + ImageCeeCsCallconvField = 0x6, + ImageCeeCsCallconvLocalSig = 0x7, + ImageCeeCsCallconvProperty = 0x8, + ImageCeeCsCallconvUnmgd = 0x9, + ImageCeeCsCallconvGenericinst = 0xa, + // generic method instantiation + ImageCeeCsCallconvNativevararg = 0xb, + // used ONLY for 64bit vararg PInvoke calls + ImageCeeCsCallconvMax = 0xc, // first invalid calling convention + + + // The high bits of the calling convention convey additional info + ImageCeeCsCallconvMask = 0x0f, + // Calling convention is bottom 4 bits + ImageCeeCsCallconvHasthis = 0x20, + // Top bit indicates a 'this' parameter + ImageCeeCsCallconvExplicitthis = 0x40, + // This parameter is explicitly in the signature + ImageCeeCsCallconvGeneric = 0x10, // Generic method sig with explicit number of type arguments (precedes ordinary parameter count) + // 0x80 is reserved for internal use +} + + +#[derive(Copy, Clone, Debug, PartialEq)] +#[repr(C)] +pub enum CorElementType +{ + ElementTypeEnd = 0x00, + ElementTypeVoid = 0x01, + ElementTypeBoolean = 0x02, + ElementTypeChar = 0x03, + ElementTypeI1 = 0x04, + ElementTypeU1 = 0x05, + ElementTypeI2 = 0x06, + ElementTypeU2 = 0x07, + ElementTypeI4 = 0x08, + ElementTypeU4 = 0x09, + ElementTypeI8 = 0x0a, + ElementTypeU8 = 0x0b, + ElementTypeR4 = 0x0c, + ElementTypeR8 = 0x0d, + ElementTypeString = 0x0e, + + // every type above PTR will be simple type + ElementTypePtr = 0x0f, + // PTR + ElementTypeByref = 0x10, // BYREF + + // Please use ElementTypeValuetype. ELEMENT_TYPE_VALUECLASS is deprecated. + ElementTypeValuetype = 0x11, + // VALUETYPE + ElementTypeClass = 0x12, + // CLASS + ElementTypeVar = 0x13, + // a class type variable VAR + ElementTypeArray = 0x14, + // MDARRAY ... ... + ElementTypeGenericinst = 0x15, + // GENERICINST ... + ElementTypeTypedbyref = 0x16, // TYPEDREF (it takes no args) a typed referece to some other type + + ElementTypeI = 0x18, + // native integer size + ElementTypeU = 0x19, + // native unsigned integer size + ElementTypeFnptr = 0x1b, + // FNPTR + ElementTypeObject = 0x1c, + // Shortcut for System.Object + ElementTypeSzarray = 0x1d, + // Shortcut for single dimension zero lower bound array +// SZARRAY + ElementTypeMvar = 0x1e, // a method type variable MVAR + + // This is only for binding + ElementTypeCmodReqd = 0x1f, + // required C modifier : E_T_CMOD_REQD + ElementTypeCmodOpt = 0x20, // optional C modifier : E_T_CMOD_OPT + + // This is for signatures generated internally (which will not be persisted in any way). + ElementTypeInternal = 0x21, // INTERNAL + + // Note that this is the max of base type excluding modifiers + ElementTypeMax = 0x22, // first invalid element type + + + ElementTypeModifier = 0x40, + ElementTypeSentinel = 0x01 | 0x40, + // sentinel for varargs + ElementTypePinned = 0x05 | 0x40, + +} + +impl From for CorElementType { + fn from(cet: core_bindings::CorElementType) -> Self { + match cet { + core_bindings::CorElementType::ELEMENT_TYPE_END => CorElementType::ElementTypeEnd, + core_bindings::CorElementType::ELEMENT_TYPE_VOID => CorElementType::ElementTypeVoid, + core_bindings::CorElementType::ELEMENT_TYPE_BOOLEAN => CorElementType::ElementTypeBoolean, + core_bindings::CorElementType::ELEMENT_TYPE_CHAR => CorElementType::ElementTypeChar, + core_bindings::CorElementType::ELEMENT_TYPE_I1 => CorElementType::ElementTypeI1, + core_bindings::CorElementType::ELEMENT_TYPE_U1 => CorElementType::ElementTypeU1, + core_bindings::CorElementType::ELEMENT_TYPE_I2 => CorElementType::ElementTypeI2, + core_bindings::CorElementType::ELEMENT_TYPE_U2 => CorElementType::ElementTypeU2, + core_bindings::CorElementType::ELEMENT_TYPE_I4 => CorElementType::ElementTypeI4, + core_bindings::CorElementType::ELEMENT_TYPE_U4 => CorElementType::ElementTypeU4, + core_bindings::CorElementType::ELEMENT_TYPE_I8 => CorElementType::ElementTypeI8, + core_bindings::CorElementType::ELEMENT_TYPE_U8 => CorElementType::ElementTypeU8, + core_bindings::CorElementType::ELEMENT_TYPE_R4 => CorElementType::ElementTypeR4, + core_bindings::CorElementType::ELEMENT_TYPE_R8 => CorElementType::ElementTypeR8, + core_bindings::CorElementType::ELEMENT_TYPE_STRING => CorElementType::ElementTypeString, + core_bindings::CorElementType::ELEMENT_TYPE_PTR => CorElementType::ElementTypePtr, + core_bindings::CorElementType::ELEMENT_TYPE_BYREF => CorElementType::ElementTypeByref, + core_bindings::CorElementType::ELEMENT_TYPE_VALUETYPE => CorElementType::ElementTypeValuetype, + core_bindings::CorElementType::ELEMENT_TYPE_CLASS => CorElementType::ElementTypeClass, + core_bindings::CorElementType::ELEMENT_TYPE_VAR => CorElementType::ElementTypeVar, + core_bindings::CorElementType::ELEMENT_TYPE_ARRAY => CorElementType::ElementTypeArray, + core_bindings::CorElementType::ELEMENT_TYPE_GENERICINST => CorElementType::ElementTypeGenericinst, + core_bindings::CorElementType::ELEMENT_TYPE_TYPEDBYREF => CorElementType::ElementTypeTypedbyref, + core_bindings::CorElementType::ELEMENT_TYPE_I => CorElementType::ElementTypeI, + core_bindings::CorElementType::ELEMENT_TYPE_U => CorElementType::ElementTypeU, + core_bindings::CorElementType::ELEMENT_TYPE_FNPTR => CorElementType::ElementTypeFnptr, + core_bindings::CorElementType::ELEMENT_TYPE_OBJECT => CorElementType::ElementTypeObject, + core_bindings::CorElementType::ELEMENT_TYPE_SZARRAY => CorElementType::ElementTypeSzarray, + core_bindings::CorElementType::ELEMENT_TYPE_MVAR => CorElementType::ElementTypeMvar, + core_bindings::CorElementType::ELEMENT_TYPE_CMOD_REQD => CorElementType::ElementTypeCmodReqd, + core_bindings::CorElementType::ELEMENT_TYPE_CMOD_OPT => CorElementType::ElementTypeCmodOpt, + core_bindings::CorElementType::ELEMENT_TYPE_INTERNAL => CorElementType::ElementTypeInternal, + core_bindings::CorElementType::ELEMENT_TYPE_MAX => CorElementType::ElementTypeMax, + core_bindings::CorElementType::ELEMENT_TYPE_MODIFIER => CorElementType::ElementTypeModifier, + core_bindings::CorElementType::ELEMENT_TYPE_SENTINEL => CorElementType::ElementTypeSentinel, + core_bindings::CorElementType::ELEMENT_TYPE_PINNED => CorElementType::ElementTypePinned, + } + } +} + + +#[derive(Debug, Clone, Copy, PartialEq)] +#[repr(C)] +pub enum CorTokenType { + mdtModule = 0x00000000, + mdtTypeRef = 0x01000000, + mdtTypeDef = 0x02000000, + mdtFieldDef = 0x04000000, + mdtMethodDef = 0x06000000, + mdtParamDef = 0x08000000, + mdtInterfaceImpl = 0x09000000, + mdtMemberRef = 0x0a000000, + mdtCustomAttribute = 0x0c000000, + mdtPermission = 0x0e000000, + mdtSignature = 0x11000000, + mdtEvent = 0x14000000, + mdtProperty = 0x17000000, + mdtModuleRef = 0x1a000000, + mdtTypeSpec = 0x1b000000, + mdtAssembly = 0x20000000, + mdtAssemblyRef = 0x23000000, + mdtFile = 0x26000000, + mdtExportedType = 0x27000000, + mdtManifestResource = 0x28000000, + mdtGenericParam = 0x2a000000, + mdtMethodSpec = 0x2b000000, + mdtGenericParamConstraint = 0x2c000000, + mdtString = 0x70000000, + mdtName = 0x71000000, + mdtBaseType = 0x72000000, + mdtError_ = 1868 +} + +impl From for CorTokenType { + fn from(value: u32) -> Self { + match value { + 0x00000000 => Self::mdtModule, + 0x01000000 => Self::mdtTypeRef, + 0x02000000 => Self::mdtTypeDef, + 0x04000000 => Self::mdtFieldDef, + 0x06000000 => Self::mdtMethodDef, + 0x08000000 => Self::mdtParamDef, + 0x09000000 => Self::mdtInterfaceImpl, + 0x0a000000 => Self::mdtMemberRef, + 0x0c000000 => Self::mdtCustomAttribute, + 0x0e000000 => Self::mdtPermission, + 0x11000000 => Self::mdtSignature, + 0x14000000 => Self::mdtEvent, + 0x17000000 => Self::mdtProperty, + 0x1a000000 => Self::mdtModuleRef, + 0x1b000000 => Self::mdtTypeSpec, + 0x20000000 => Self::mdtAssembly, + 0x23000000 => Self::mdtAssemblyRef, + 0x26000000 => Self::mdtFile, + 0x27000000 => Self::mdtExportedType, + 0x28000000 => Self::mdtManifestResource, + 0x2a000000 => Self::mdtGenericParam, + 0x2b000000 => Self::mdtMethodSpec, + 0x2c000000 => Self::mdtGenericParamConstraint, + 0x70000000 => Self::mdtString, + 0x71000000 => Self::mdtName, + 0x72000000 => Self::mdtBaseType, + _ => Self::mdtError_ + } + } +} \ No newline at end of file diff --git a/core/src/lib.rs b/core/src/lib.rs index 993d0dd..28280fc 100755 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,6 +1,8 @@ -pub mod runtime; +//pub mod runtime; pub mod metadata; pub mod bindings; +pub mod prelude; +pub mod enums; #[no_mangle] pub extern fn hello(){ diff --git a/core/src/metadata/com_helpers.rs b/core/src/metadata/com_helpers.rs index 74beb85..a0eec36 100755 --- a/core/src/metadata/com_helpers.rs +++ b/core/src/metadata/com_helpers.rs @@ -1,61 +1,84 @@ -#![allow(non_upper_case_globals)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] +use crate::prelude::*; +use crate::bindings::{helpers, imeta_data_import2, enums, rometadataresolution}; -use std::ffi::c_void; -use crate::runtime::metadata::token_type::CorTokenType; -use crate::runtime::Enums_TypeFromToken; +const GUID_ATTRIBUTE: &'static str = "Windows.Foundation.Metadata.GuidAttribute"; -pub type DWORD = u32; -pub type MdToken = u32; +pub fn get_string_value_from_blob(metadata: *mut c_void, signature: PCCOR_SIGNATURE) -> &str { + debug_assert!(!metadata.is_null()); + debug_assert!(!signature.is_null()); + if signature as u8 == u8::MAX { + return ""; + } -#[repr(C)] -#[allow(camel_case)] -pub struct IMetaDataImport2 { - GetTypeDefProps: extern fn(MdToken, *mut i8, u64, *mut u64, DWORD, *mut MdToken) -> windows::HRESULT, - GetTypeRefProps: extern fn(MdToken, *mut MdToken, *mut i8, u64, *mut u64) -> windows::HRESULT, + let size = helpers::cor_sig_uncompress_data(signature); + + let slice = unsafe { std::slice::from_raw_parts(signature as *mut u16, size as usize) }; + + OsString::from_wide(slice).to_string_lossy().as_ref() } -impl IMetaDataImport2 { - pub(crate) fn GetTypeDefProps(&mut self, mdTypeDef: MdToken, szTypeDef: &mut String, pchTypeDef: *mut u64, pdwTypeDefFlags: DWORD, ptkExtends: *mut MdToken) -> windows::HRESULT { - println!("mdTypeDef: {} szTypeDef: {} pchTypeDef: {} pdwTypeDefFlags: {} ptkExtends: {}", mdTypeDef, &szTypeDef, pchTypeDef as u64, pdwTypeDefFlags, ptkExtends as u32); - (self.GetTypeDefProps)(mdTypeDef, szTypeDef.as_mut_ptr() as *mut i8, szTypeDef.len() as u64, pchTypeDef, pdwTypeDefFlags, ptkExtends) - } - fn GetTypeRefProps(&mut self, tkTypeRef: MdToken, mut ptkResolutionScope: MdToken, szName: &mut String, pchName: *mut u64) -> windows::HRESULT { - (self.GetTypeRefProps)(tkTypeRef, &mut ptkResolutionScope, szName.as_mut_ptr() as *mut i8, szName.len() as u64, pchName) - } + +pub fn get_unary_custom_attribute_string_value(metadata: *mut c_void, token: mdToken, attribute_name: &str) -> &str { + debug_assert!(!metadata.is_null()); + debug_assert!(token != mdTokenNil); + debug_assert!(!attribute_name.is_null()); + + + let mut data = vec![0_u8; MAX_IDENTIFIER_LENGTH]; + let name = OsString::from(attribute_name.to_owned()).to_wide(); + let data_ptr = &data.as_mut_ptr() as *mut *const c_void; + let result = imeta_data_import2::get_custom_attribute_by_name( + metadata, token, Some(name.as_ptr()), Some(data_ptr), None, + ); + debug_assert!( + result.is_ok() + ); + if result.is_err() { + return ""; + } + + get_string_value_from_blob(metadata, data + 2) } -pub(crate) fn get_type_name(metadata: *mut c_void, md_token: u32) -> String { - assert!(!metadata.is_null()); - assert!(md_token == 0); - let mut name_data = String::new(); - let mut name_length = 0_u64; - - let mut metadata: *mut IMetaDataImport2 = unsafe {std::mem::transmute(metadata)}; - let mut metadata = unsafe { &mut *metadata }; - unsafe { - println!("asdasda {:?}", Enums_TypeFromToken(md_token)); - match Enums_TypeFromToken(md_token).into() { - CorTokenType::MdtTypeDef => { - println!("MdtTypeDef"); - assert!(metadata.GetTypeDefProps(md_token, &mut name_data, &mut name_length, 0, &mut 0).is_err()) - } - CorTokenType::MdtTypeRef => { - println!("MdtTypeRef"); - assert!(metadata.GetTypeRefProps(md_token, 0, &mut name_data, &mut name_length).is_err()) - } - _ => { - assert!(true) - } - } - } - - println!("name_data {:?} : name_length {:?}", &name_data, name_length); - - return name_data + +pub fn resolve_type_ref(metadata: *mut c_void, token: mdTypeRef, external_metadata: *mut *mut c_void, external_token: *mut mdTypeDef) -> bool { + debug_assert!(!metadata.is_null()); + debug_assert!(enums::type_from_token(token) == CorTokenType::mdtTypeRef as u32); + debug_assert!(!external_metadata.is_null()); + debug_assert!(!external_token.is_null()); + + let mut data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + debug_assert!( + imeta_data_import2::get_type_ref_props( + metadata, token, None, Some(data.as_mut_ptr()), Some(data.len() as u32), None, + ).is_ok() + ); + let mut string = windows::HSTRING::from_wide(data.as_slice()); + rometadataresolution::ro_get_meta_data_file( + &mut string, None, None, Some(external_metadata), Some(external_token), + ).is_ok() } -fn get_type_def_props() {} \ No newline at end of file + +pub fn get_guid_attribute_value(metadata: *mut c_void, token: mdToken) -> GUID { + debug_assert!(!metadata.is_null()); + debug_assert!(token != mdTokenNil); + let mut size = 0; + let mut data = vec![0_u8; MAX_IDENTIFIER_LENGTH]; + let name = OsString::from(GUID_ATTRIBUTE).to_wide(); + let data_ptr = &data.as_mut_ptr() as *mut *const c_void; + imeta_data_import2::get_custom_attribute_by_name( + metadata, token, Some(name.as_ptr()), Some(data_ptr), Some(&mut size), + ); + data.resize(size as _, 0); + + // Skip prolog + let os_data = unsafe { data.as_mut_ptr().offset(2) }; + let mut guid = GUID::default(); + helpers::bytes_to_guid( + os_data, &mut guid, + ); + guid +} diff --git a/core/src/metadata/declaration_factory.rs b/core/src/metadata/declaration_factory.rs new file mode 100644 index 0000000..32bbf2f --- /dev/null +++ b/core/src/metadata/declaration_factory.rs @@ -0,0 +1,93 @@ +use crate::prelude::*; +use crate::bindings::enums; +use crate::metadata::declarations::delegate_declaration::DelegateDeclaration; +use crate::bindings::rometadataresolution; +use crate::metadata::com_helpers::resolve_type_ref; +use std::sync::Arc; +use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; + +pub struct DeclarationFactory {} + +impl DeclarationFactory { + pub fn make_delegate_declaration(metadata: *mut c_void, token: mdToken) -> DelegateDeclaration{ + match enums::type_from_token(token) as CorTokenType + { + CorTokenType::mdtTypeDef => DelegateDeclaration::new(metadata, token), + CorTokenType::mdtTypeRef => { + let mut external_metadata = std::ptr::null_mut(); + let mut external_delegate_token = mdTokenNil; + let is_resolved = resolve_type_ref(metadata, token, &mut external_metadata,&mut external_delegate_token); + debug_assert!(is_resolved); + DelegateDeclaration::new(external_metadata, external_delegate_token) + } + CorTokenType::mdtTypeSpec => {} + _ => { + std::unreachable!() + } + } + } + pub fn make_interface_declaration(metadata: *mut c_void, token: mdToken): { + + match enums::type_from_token(token){ + mdtTypeDef => { + return Some( + Arc::new( + InterfaceDeclaration::new(metadata, token) + ) + ) + } + } + switch (TypeFromToken(token)) { + case mdtTypeDef: { + return make_unique(metadata, token); + } + + case mdtTypeRef: { + ComPtr externalMetadata; + mdTypeDef externalInterfaceToken{ mdTokenNil }; + + bool isResolved{ resolveTypeRef(metadata, token, externalMetadata.GetAddressOf(), &externalInterfaceToken) }; + ASSERT(isResolved); + + return make_unique(externalMetadata.Get(), externalInterfaceToken); + } + + case mdtTypeSpec: { + PCCOR_SIGNATURE signature{ nullptr }; + ULONG signatureSize{ 0 }; + ASSERT_SUCCESS(metadata->GetTypeSpecFromToken(token, &signature, &signatureSize)); + + CorElementType type1{ CorSigUncompressElementType(signature) }; + ASSERT(type1 == ELEMENT_TYPE_GENERICINST); + + CorElementType type2{ CorSigUncompressElementType(signature) }; + ASSERT(type2 == ELEMENT_TYPE_CLASS); + + mdToken openGenericDelegateToken{ CorSigUncompressToken(signature) }; + switch (TypeFromToken(openGenericDelegateToken)) { + case mdtTypeDef: { + return make_unique(metadata, openGenericDelegateToken, metadata, token); + } + + case mdtTypeRef: { + ComPtr externalMetadata; + mdTypeDef externalDelegateToken{ mdTokenNil }; + + bool isResolved{ resolveTypeRef(metadata, openGenericDelegateToken, externalMetadata.GetAddressOf(), &externalDelegateToken) }; + ASSERT(isResolved); + + return make_unique(externalMetadata.Get(), externalDelegateToken, metadata, token); + } + + default: + ASSERT_NOT_REACHED(); + } + + break; + } + + default: + ASSERT_NOT_REACHED(); + } + } +} \ No newline at end of file diff --git a/core/src/metadata/declarations/base_class_declaration.rs b/core/src/metadata/declarations/base_class_declaration.rs new file mode 100644 index 0000000..6b12ff4 --- /dev/null +++ b/core/src/metadata/declarations/base_class_declaration.rs @@ -0,0 +1,238 @@ +use crate::{ + prelude::*, + metadata::declarations::type_declaration::TypeDeclaration, + metadata::declarations::interface_declaration::InterfaceDeclaration, + metadata::declarations::method_declaration::MethodDeclaration, + metadata::declarations::property_declaration::PropertyDeclaration, + metadata::declarations::event_declaration::EventDeclaration, + bindings::imeta_data_import2, +}; +use crate::metadata::declarations::declaration::{DeclarationKind, Declaration}; + +use crate::metadata::declaration_factory::DeclarationFactory; + +use std::str::FromStr; +use std::borrow::Cow; + +pub struct BaseClassDeclaration<'a> { + base: TypeDeclaration<'a>, + implemented_interfaces: Vec>, + methods: Vec>, + properties: Vec>, + events: Vec>, +} + +impl BaseClassDeclaration { + fn make_implemented_interfaces_declarations(metadata: *mut c_void, token: mdTypeDef) { + let mut enumerator = std::ptr::null_mut(); + let enumer = &mut enumerator; + let mut count = 0; + let mut tokens = [0; 1024]; + + debug_assert!( + imeta_data_import2::enum_interface_impls( + metadata, enumer, Some(token), Some(tokens.as_mut_ptr()), Some(tokens.len() as u32), Some(&mut count), + ).is_ok() + ); + + debug_assert!(count < (tokens.len() - 1) as u32); + imeta_data_import2::close_enum(metadata, enumerator); + + let mut result = Vec::new(); + for i in 0..count { + let mut interface_token = mdTokenNil; + debug_assert!( + imeta_data_import2::get_interface_impl_props( + metadata, tokens[i], None, Some(&mut interface_token), + ).is_ok() + ); + result.push( + DeclarationFactory::make_interface_declaration( + metadata, interface_token, + ) + ); + } + + result + } + + fn make_method_declarations(metadata: *mut c_void, token: mdTypeDef) -> Vec { + let enumerator = std::ptr::null_mut(); + let mut count = 0; + let mut tokens = [0; 1024]; + debug_assert!( + imeta_data_import2::enum_methods( + metadata, enumerator, token, tokens.as_mut_ptr(), tokens.len(), &mut count, + ).is_ok() + ); + + debug_assert!(count < tokens.len() - 1); + imeta_data_import2::close_enum(metadata, enumerator); + + let mut result = Vec::new(); + for i in 0..count { + let method = MethodDeclaration::new(metadata, tokens[i]); + if !method.is_exported() { + continue; + } + result.push(method); + } + + return result; + } + + fn make_property_declarations(metadata: *mut c_void, token: mdTypeDef) -> Vec { + let enumerator = std::ptr::null_mut(); + let mut count = 0; + let mut tokens = [0; 1024]; + debug_assert!( + imeta_data_import2::enum_pr + ); + + debug_assert!( + imeta_data_import2::enum_properties( + metadata, enumerator, token, tokens.as_mut_ptr(), tokens.len(), &mut count, + ).is_ok() + ); + debug_assert!(count < tokens.len() - 1); + imeta_data_import2::close_enum(metadata, enumerator); + + let mut result = Vec::new(); + for i in 0..count { + let property = PropertyDeclaration::new(metadata, tokens[i]); + if !property.is_exported() { + continue; + } + result.push(property); + } + result + } + + fn make_event_declarations(metadata: *mut c_void, token: mdTypeDef) -> Vec { + let enumerator = std::ptr::null_mut(); + let mut count = 0; + let mut tokens = [0; 1024]; + + debug_assert!( + imeta_data_import2::enum_events( + metadata, enumerator, token, tokens.as_mut_ptr(), tokens.len(), &mut count, + ).is_ok() + ); + debug_assert!(count < tokens.len() - 1); + imeta_data_import2::close_enum(metadata, enumerator); + + let mut result = Vec::new(); + for i in 0..count { + let event = EventDeclaration::new(metadata, tokens[i]); + if !event.is_exported() { + continue; + } + result.push(event); + } + + result + } + + pub fn new(kind: DeclarationKind, metadata: *mut c_void, token: mdTypeDef) -> Self { + Self { + base: TypeDeclaration::new(kind, metadata, token), + implemented_interfaces: BaseClassDeclaration::make_implemented_interfaces_declarations(metadata, token), + methods: BaseClassDeclaration::make_method_declarations(metadata, token), + properties: BaseClassDeclaration::make_property_declarations(metadata, token), + events: BaseClassDeclaration::make_event_declarations(metadata, token), + } + } +} + +pub trait BaseClassDeclarationImpl { + fn base(&self) -> &TypeDeclaration; + + fn implemented_interfaces(&self) -> &Vec; + + fn methods(&self) -> &Vec; + + fn properties(&self) -> &Vec; + + fn events(&self) -> &Vec; + + fn find_members_with_name(&self, name: &str) -> Vec { + debug_assert!(name); + + let mut result = Vec::new(); + + let mut methods: Vec = self.find_methods_with_name(name); + result.append(&mut methods); + + let mut properties = self.properties().iter().filter(|prop| prop.full_name() == name).collect(); + result.append(&mut properties); + + let mut events = self.events().iter().filter(|event| event.full_name() == name).collect(); + result.append(&mut events); + + return result; + } + + fn find_methods_with_name(&self, name: &str) -> Vec { + debug_assert!(name); + + let enumerator = std::ptr::null_mut(); + let mut method_tokens: Vec = vec![0; 1024]; + let mut methods_count = 0; + let name = OsString::from_str(name).unwrap_or_default().to_wide(); + let base = self.base(); + debug_assert!( + imeta_data_import2::enum_methods_with_name( + base.metadata, base.token, enumerator, name.as_ptr(), + method_tokens.as_mut_ptr(), method_tokens.len(), &mut methods_count, + ).is_ok() + ); + imeta_data_import2::close_enum(base.metadata, enumerator); + + let mut result = Vec::new(); + for i in 0..methods_count { + let method_token = method_tokens[i]; + result.push( + MethodDeclaration::new(base.metadata, method_token) + ) + } + + return result; + } +} + +impl BaseClassDeclarationImpl for BaseClassDeclaration { + fn base<'a>(&self) -> &TypeDeclaration<'a> { + &self.base + } + + fn implemented_interfaces<'a>(&self) -> &Vec> { + &self.implemented_interfaces + } + + fn methods<'a>(&self) -> &Vec> { + &self.methods + } + + fn properties<'a>(&self) -> &Vec> { + &self.properties + } + + fn events<'a>(&self) -> &Vec> { + &self.events + } +} + +impl Declaration for BaseClassDeclaration { + fn name<'a>(&self) -> Cow<'a, str> { + self.full_name() + } + + fn full_name<'a>(&self) -> Cow<'a, str> { + self.base().full_name() + } + + fn kind(&self) -> DeclarationKind { + self.base().kind + } +} + diff --git a/core/src/metadata/declarations/class_declaration.rs b/core/src/metadata/declarations/class_declaration.rs new file mode 100644 index 0000000..a9b8fb0 --- /dev/null +++ b/core/src/metadata/declarations/class_declaration.rs @@ -0,0 +1,141 @@ +use crate::prelude::*; +use crate::{ + metadata::declarations::method_declaration::MethodDeclaration, + metadata::declarations::interface_declaration::InterfaceDeclaration +}; + +use crate::bindings::{helpers, imeta_data_import2}; +use std::str::FromStr; +use crate::metadata::declaration_factory::DeclarationFactory; +use std::sync::Arc; +use crate::metadata::declarations::base_class_declaration::BaseClassDeclaration; +use crate::metadata::declarations::declaration::DeclarationKind; + + +const DEFAULT_ATTRIBUTE:&'static str = "Windows.Foundation.Metadata.DefaultAttribute"; + +pub struct ClassDeclaration<'a> { + initializers: Vec>, + default_interface: InterfaceDeclaration<'a>, + base: BaseClassDeclaration<'a> +} + +impl ClassDeclaration { + + fn make_initializer_declarations(metadata: *mut c_void, token: mdTypeDef) -> Vec{ + let enumerator = std::ptr::null_mut(); + let mut count = 0; + let mut tokens:Vec = vec![0;1024]; + + let name = OsString::from_str(COR_CTOR_METHOD_NAME).unwrap(); + let name = name.to_wide(); + debug_assert!( + imeta_data_import2::enum_methods_with_name( + metadata, enumerator, token, name.as_ptr(), tokens.as_mut_ptr(), + tokens.len(), &mut count + ).is_ok() + ); + + debug_assert!(count < tokens.len() - 1); + + imeta_data_import2::close_enum(metadata, enumerator); + + let mut result = Vec::new(); + for i in 0..count { + let method_token = tokens[i]; + + // TODO: Make a InstanceInitializerDeclaration and check this in it's isExported method + let mut flags = 0; + debug_assert!( + imeta_data_import2::get_method_props( + metadata, method_token, None, None, + None, None, Some(&mut flags), None, None, + None, None + ).is_ok() + ); + + if helpers::is_md_public(flags) { + continue; + } + + result.push( + MethodDeclaration::new(metadata, method_token) + ); + } + + return result; + } + + fn make_default_interface(metadata: *mut c_void, token: mdTypeDef) -> Option> { + let mut interface_impl_tokens = vec![0_1024]; + let mut interface_impl_count = 0; + let interface_enumerator = std::ptr::null_mut(); + debug_assert!( + imeta_data_import2::enum_interface_impls( + metadata, interface_enumerator, token, + Some(interface_impl_tokens.as_mut_ptr()), Some(interface_impl_tokens.len()), + Some(&mut interface_impl_count) + ).is_ok() + ); + + debug_assert!(interface_impl_count < interface_impl_tokens.size()); + imeta_data_import2::close_enum(metadata, interface_enumerator); + let attr = OsString::from_str(DEFAULT_ATTRIBUTE).unwrap().to_wide(); + for i in 0..interface_impl_count { + let interface_impl_token = interface_impl_tokens[i]; + let get_custom_attribute_result = imeta_data_import2::get_custom_attribute_by_name( + metadata, interface_impl_token, Some(attr.as_ptr()), None, None + ); + debug_assert!(get_custom_attribute_result.is_ok()); + if get_custom_attribute_result.is_ok() { + let mut interface_token = mdTokenNil; + debug_assert!( + imeta_data_import2::get_interface_impl_props( + metadata, interface_impl_token, None, Some(&mut interface_token) + ).is_ok() + ); + return Some( + Arc::new( + DeclarationFactory::make_interface_declaration(metadata, interface_token) + ) + ) + } + } + + std::unreachable!() + } + + pub fn new(metadata: *mut c_void, token: mdTypeDef)-> Self { + Self { + initializers: ClassDeclaration::make_initializer_declarations(metadata, token), + default_interface: ClassDeclaration::make_default_interface(metadata, token), + base: BaseClassDeclaration::new( + DeclarationKind::Class, metadata, token + ) + } + } + + pub fn base_full_name(&self) -> &str { + let mut parentToken = mdTokenNil; + debug_assert!( + imeta_data_import2::get_type_def_props( + self.base + ) + ); + ASSERT_SUCCESS(_metadata->GetTypeDefProps(_token, nullptr, 0, nullptr, nullptr, &parentToken)); + + return getTypeName(_metadata.Get(), parentToken); + } + + pub fn default_interface(&self) -> &InterfaceDeclaration{ + &self.default_interface + } + + pub fn is_instantiable(&self) -> bool {} + + pub fn is_sealed(&self) -> bool {} + + pub fn initializers(&self) -> { + // self.initializers.iter() + } +} \ No newline at end of file diff --git a/core/src/metadata/declarations/declaration.rs b/core/src/metadata/declarations/declaration.rs index 0f51a63..f31fd39 100644 --- a/core/src/metadata/declarations/declaration.rs +++ b/core/src/metadata/declarations/declaration.rs @@ -1,32 +1,41 @@ +use std::borrow::Cow; +use std::any::Any; + #[derive(Copy, Clone, Debug, PartialEq)] pub enum DeclarationKind { - Namespace, - Class, - Interface, - GenericInterface, - GenericInterfaceInstance, - Enum, - EnumMember, - Struct, - StructField, - Delegate, - GenericDelegate, - GenericDelegateInstance, - Event, - Property, - Method, - Parameter, + Namespace, + Class, + Interface, + GenericInterface, + GenericInterfaceInstance, + Enum, + EnumMember, + Struct, + StructField, + Delegate, + GenericDelegate, + GenericDelegateInstance, + Event, + Property, + Method, + Parameter, } pub trait Declaration { - fn is_exported(&self) -> bool; + fn is_exported(&self) -> bool { + return true; + } + + /// Specifies the simple name (e.g., "String" rather than "System.String") of a given type. + fn name<'a>(&self) -> Cow<'a, str>; - /// Specifies the simple name (e.g., "String" rather than "System.String") of a given type. - fn name<'a>(&self) -> &'a str ; + /// Specifies the fully-qualified name of a given type. + /// For generic types, this includes the spelling of generic parameter names. + fn full_name<'a>(&self) -> Cow<'a, str>; - /// Specifies the fully-qualified name of a given type. - /// For generic types, this includes the spelling of generic parameter names. - fn full_name<'a>(&self) -> &'a str; + fn kind(&self) -> DeclarationKind; - fn kind(&self) -> DeclarationKind; + fn as_any(&self) -> &dyn Any { + self + } } diff --git a/core/src/metadata/declarations/delegate_declaration/mod.rs b/core/src/metadata/declarations/delegate_declaration/mod.rs new file mode 100644 index 0000000..ce60215 --- /dev/null +++ b/core/src/metadata/declarations/delegate_declaration/mod.rs @@ -0,0 +1,161 @@ +use crate::prelude::*; +use crate::metadata::declarations::type_declaration::TypeDeclaration; +use crate::metadata::declarations::method_declaration::MethodDeclaration; +use crate::bindings::{imeta_data_import2, enums}; +use crate::metadata::declarations::declaration::{DeclarationKind, Declaration}; +use crate::metadata::com_helpers::get_guid_attribute_value; +use crate::metadata::signature::Signature; + +const INVOKE_METHOD_NAME: &'static str = "Invoke"; + +pub fn get_invoke_method_token(meta_data: *mut c_void, token: mdTypeDef) -> mdMethodDef { + let mut invoke_method_token = mdTokenNil; + let string = OsString::from(INVOKE_METHOD_NAME); + debug_assert!( + imeta_data_import2::find_method( + meta_data, token, string.to_wide().as_ptr(), None, 0, &mut invoke_method_token, + ) + ); + return invoke_method_token; +} + +pub struct DelegateDeclaration<'a> { + base: TypeDeclaration<'a>, + invoke_method: MethodDeclaration<'a>, +} + +impl DelegateDeclaration { + pub fn new(metadata: *mut c_void, token: mdTypeDef) -> Self { + Self::new_overload( + DeclarationKind::Delegate, metadata, token, + ) + } + + pub fn new_overload(kind: DeclarationKind, metadata: *mut c_void, token: mdTypeDef) -> Self { + Self { + base: TypeDeclaration::new( + kind, metadata, token, + ), + invoke_method: MethodDeclaration::new( + metadata, get_invoke_method_token(metadata, token), + ), + } + } + + pub fn id(&self) -> GUID { + get_guid_attribute_value(self.base.metadata, self.base.token) + } + + pub fn invoke_method<'a>(&self) -> &MethodDeclaration<'a> { + &self.invoke_method + } +} + +pub struct GenericDelegateDeclaration<'a> { + base: DelegateDeclaration<'a>, +} + +impl GenericDelegateDeclaration { + pub fn new(metadata: *mut c_void, token: mdToken) -> Self { + Self { + base: DelegateDeclaration::new_overload( + DeclarationKind::GenericDelegate, metadata, token, + ) + } + } + + pub fn number_of_generic_parameters(&self) -> usize { + let mut count = 0; + + let mut enumerator = std::ptr::null_mut(); + let enumer = &mut enumerator; + + debug_assert!( + imeta_data_import2::enum_generic_params(self.base.base.metadata, enumer, self.base.base.token, None, None, None).is_ok() + ); + debug_assert!( + imeta_data_import2::count_enum(self.base.base.metadata, enumerator, &mut count).is_ok() + ); + imeta_data_import2::close_enum(self.base.base.metadata, enumerator); + + return count as usize; + } +} + +pub struct GenericDelegateInstanceDeclaration<'a> { + base: DelegateDeclaration<'a>, + closed_token: mdTypeSpec, + closed_metadata: *mut c_void, +} + +impl GenericDelegateInstanceDeclaration { + pub fn new(open_metadata: *mut c_void, open_token: mdTypeDef, closed_metadata: *mut c_void, closed_token: mdTypeSpec) -> Self { + + debug_assert!(!closed_metadata.is_null()); + debug_assert!(enums::type_from_token(closed_token) == CorTokenType::ComdtTypeSpec as u32); + debug_assert!(closed_token != mdTypeSpecNil); + + Self { + base: DelegateDeclaration::new_overload( + DeclarationKind::GenericDelegateInstance, open_metadata, open_token, + ), + closed_token, + closed_metadata, + } + } + +pub fn id(&self) -> CLSID { + GenericInstanceIdBuilder::generate_Id(self) +} +} + +impl Declaration for DelegateDeclaration { + fn name<'a>(&self) -> &'a str { + self.base.name() + } + + fn full_name<'a>(&self) -> &'a str { + self.base.full_name() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind + } +} + +impl Declaration for GenericDelegateDeclaration { + fn name<'a>(&self) -> &'a str { + self.base.name() + } + + fn full_name<'a>(&self) -> &'a str { + self.base.full_name() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind + } +} + +impl Declaration for GenericDelegateInstanceDeclaration { + fn name<'a>(&self) -> &'a str { + self.base.name() + } + + fn full_name<'a>(&self) -> &'a str { + let mut signature = vec![0_u8; MAX_IDENTIFIER_LENGTH]; + let mut sig = signature.as_ptr(); + let mut signature_size = 0; + debug_assert!( + imeta_data_import2::get_type_spec_from_token( + self.closed_metadata, self.closed_token,&mut sig,&mut signature_size + ) + ); + signature.resize(signature_size as usize, 0); + return Signature::to_string(self.closed_metadata, sig); + } + + fn kind(&self) -> DeclarationKind { + self.base.kind + } +} \ No newline at end of file diff --git a/core/src/metadata/declarations/enum_declaration.rs b/core/src/metadata/declarations/enum_declaration.rs index 012ece8..812c30b 100644 --- a/core/src/metadata/declarations/enum_declaration.rs +++ b/core/src/metadata/declarations/enum_declaration.rs @@ -8,18 +8,31 @@ use super::{ type_declaration::TypeDeclaration, }; -pub struct EnumDeclaration { - type_declaration: TypeDeclaration, +#[derive(Debug)] +pub struct EnumDeclaration<'a> { + type_declaration: TypeDeclaration<'a>, } impl Declaration for EnumDeclaration { + fn is_exported(&self) -> bool { + self.type_declaration.is_exported() + } + + fn name<'a>(&self) -> &'a str { + self.type_declaration.name() + } + + fn full_name<'a>(&self) -> &'a str { + self.type_declaration.full_name() + } + fn kind(&self) -> DeclarationKind { self.type_declaration.kind } } impl EnumDeclaration { - pub fn new(metadata: *const c_void, token: mdTypeDef) -> Self { + pub fn new(metadata: *mut c_void, token: mdTypeDef) -> Self { Self { type_declaration: TypeDeclaration::new(DeclarationKind::Enum, metadata, token) } diff --git a/core/src/metadata/declarations/event_declaration.rs b/core/src/metadata/declarations/event_declaration.rs new file mode 100644 index 0000000..a6e4b97 --- /dev/null +++ b/core/src/metadata/declarations/event_declaration.rs @@ -0,0 +1,129 @@ +use crate::prelude::*; +use crate::bindings::{imeta_data_import2, helpers}; +use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; +use crate::metadata::declarations::type_declaration::TypeDeclaration; +use std::sync::Arc; +use crate::metadata::declarations::delegate_declaration::DelegateDeclaration; +use crate::metadata::declarations::method_declaration::MethodDeclaration; +use std::ffi::c_void; +use crate::metadata::declaration_factory::DeclarationFactory; +use std::borrow::Cow; + +pub struct EventDeclaration<'a> { + base: TypeDeclaration<'a>, + type_: Arc>, + add_method: MethodDeclaration<'a>, + remove_method: MethodDeclaration<'a>, +} + +impl EventDeclaration { + pub fn make_add_method(metadata: *mut c_void, token: mdEvent) -> MethodDeclaration { + let mut add_method_token = mdTokenNil; + debug_assert!( + imeta_data_import2::get_event_props( + metadata, token, None, None, None, + None, None, None, Some(&mut add_method_token), + None, None, None, None, None, + ).is_ok() + ); + MethodDeclaration::new(metadata, add_method_token) + } + + pub fn make_remove_method(metadata: *mut c_void, token: mdEvent) -> MethodDeclaration { + let mut remove_method_token = mdTokenNil; + debug_assert!( + imeta_data_import2::get_event_props( + metadata, token, None, None, None, + None, None, None, None, + Some(&mut remove_method_token), None, None, None, + None, + ) + ); + + MethodDeclaration::new(metadata, removeMethodToken) + } + + pub fn make_type(metadata: *mut c_void, token: mdEvent) -> DelegateDeclaration { + let mut delegate_token = mdTokenNil; + debug_assert!( + imeta_data_import2::get_event_props( + metadata, token, None, None, None, None, None, + Some(&mut delegate_token), None, None, None, None, None, None, + ).is_ok() + ); + return DeclarationFactory::make_delegate_declaration(metadata, delegate_token); + } + + + pub fn new(metadata: *mut c_void, token: mdEvent) -> Self { + Self { + base: TypeDeclaration::new(DeclarationKind::Event, metadata, token), + type_: EventDeclaration::make_type(metadata, token), + add_method: EventDeclaration::make_add_method(metadata, token), + remove_method: EventDeclaration::make_remove_method(metadata, token), + } + } + + pub fn is_static(&self) -> bool { + self.add_method.is_static() + } + + pub fn is_sealed(&self) -> bool { + self.add_method.is_sealed() + } + + pub fn type_(&self) -> &DelegateDeclaration { + &self.type_ + } + + + pub fn add_method(&self) -> &MethodDeclaration { + &self.add_method + } + + pub fn remove_method(&self) -> &MethodDeclaration { + &self.remove_method + } +} + +impl Declaration for EventDeclaration { + fn is_exported(&self) -> bool { + let mut flags = 0; + debug_assert!( + imeta_data_import2::get_event_props( + self.base.metadata, self.base.token, + None, None, None, None, + Some(&mut flags), None, None, + None, None, None, None, None, + ).is_ok() + ); + if helpers::is_ev_special_name(flags) { + return false; + } + + return true; + } + + fn name<'a>(&self) -> Cow<'a, str> { + self.full_name() + } + + fn full_name<'a>(&self) -> Cow<'a, str> { + let mut name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; + let mut name_data_length = 0; + + debug_assert!( + imeta_data_import2::get_event_props( + self.base.metadata, self.base.token, + None, Some(name_data.as_mut_ptr()), Some(name_data.len()), + Some(&mut name_data_length), None, None, None, + None, None, None, None, None, + ).is_ok() + ); + OsString::from_wide(&name_data[..name_data_length]).into() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind + } +} \ No newline at end of file diff --git a/core/src/metadata/declarations/field_declaration.rs b/core/src/metadata/declarations/field_declaration.rs index e8854bb..93c3f3c 100644 --- a/core/src/metadata/declarations/field_declaration.rs +++ b/core/src/metadata/declarations/field_declaration.rs @@ -11,30 +11,12 @@ use std::ffi::{OsString}; pub struct FieldDeclaration <'a>{ pub kind: DeclarationKind, - pub metadata: *const c_void, - pub token: mdTypeDef, + pub metadata: *mut c_void, + pub token: mdFieldDef, _marker: marker::PhantomData<&'a *const c_void> } impl Declaration for FieldDeclaration { - fn kind(&self) -> DeclarationKind{ - self.kind - } - - fn is_exported(&self) -> bool { - let mut flags: DWORD = 0; - assert( - imeta_data_import2::get_type_def_props( - self.token, 0, 0,0, &mut flags, 0 - ).is_ok() - ); - - if !helpers::is_td_public(flags) || helpers::is_td_special_name(flags) { - return false; - } - - return true; - } fn name<'b>(&self) -> &'b str { return self.full_name(); @@ -42,15 +24,28 @@ impl Declaration for FieldDeclaration { fn full_name<'b>(&self) -> &'b str { let mut full_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + let mut length = 0; + debug_assert!(imeta_data_import2::get_field_props( + self.metadata, self.token, None, + Some(full_name_data.as_mut_ptr()), + Some(full_name_data.len() as u32), + Some(&mut length), + None,None, + None, None, + None,None + ).is_ok()); - let length = helpers::(self.metadata, self.token, full_name_data.as_mut_ptr(), full_name_data.len()); full_name_data.resize(length as usize, 0); - OsString::from_wide(name.as_slice()) + OsString::from_wide(name.as_slice()).to_string_lossy().as_ref() + } + + fn kind(&self) -> DeclarationKind{ + self.kind } } impl FieldDeclaration { - pub fn new(kind: DeclarationKind, metadata: *const c_void, token: mdTypeDef) -> Self { + pub fn new(kind: DeclarationKind, metadata: *mut c_void, token: mdFieldDef) -> Self { let value = Self { kind, metadata, @@ -59,8 +54,8 @@ impl FieldDeclaration { }; assert!(value.metadata.is_not_null()); - assert!(enums::type_from_token(value.token) == mdtFieldDef); - assert!(value.token != mdTypeDefNil); + assert!(enums::type_from_token(value.token) == CorTokenType::mdtFieldDef as u32); + assert!(value.token != mdFieldDefNil); value } } \ No newline at end of file diff --git a/core/src/metadata/declarations/interface_declaration.rs b/core/src/metadata/declarations/interface_declaration.rs new file mode 100644 index 0000000..80c20ef --- /dev/null +++ b/core/src/metadata/declarations/interface_declaration.rs @@ -0,0 +1,212 @@ +use crate::prelude::*; +use crate::metadata::declarations::base_class_declaration::{BaseClassDeclaration, BaseClassDeclarationImpl, BaseClassDeclarationImp}; +use crate::metadata::declarations::event_declaration::EventDeclaration; +use crate::metadata::declarations::method_declaration::MethodDeclaration; +use crate::metadata::declarations::property_declaration::PropertyDeclaration; +use crate::metadata::declarations::type_declaration::TypeDeclaration; +use crate::metadata::declarations::declaration::{DeclarationKind, Declaration}; +use crate::bindings::{helpers, imeta_data_import2, enums}; +use crate::metadata::com_helpers::get_guid_attribute_value; +use std::borrow::Cow; +use crate::metadata::generic_instance_id_builder::GenericInstanceIdBuilder; +use crate::metadata::signature::Signature; + +pub struct InterfaceDeclaration<'a> { + base: BaseClassDeclaration<'a>, +} + +impl InterfaceDeclaration { + pub fn new(metadata: *mut c_void, token: mdToken) -> Self { + Self::new_with_kind( + DeclarationKind::Interface, metadata, token, + ) + } + + pub fn new_with_kind(kind: DeclarationKind, metadata: *mut c_void, token: mdToken) -> Self { + Self { + base: BaseClassDeclaration::new( + kind, metadata, token, + ) + } + } + + pub fn id(&self) -> GUID { + let base = self.base.base(); + get_guid_attribute_value(base.metadata, base.token) + } +} + +impl<'a> Declaration for InterfaceDeclaration { + fn name<'a>(&self) -> Cow<'a, str> { + self.base.name() + } + + fn full_name<'a>(&self) -> Cow<'a, str> { + self.base.full_name() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind() + } +} + +impl<'a> BaseClassDeclarationImpl for InterfaceDeclaration { + fn base(&self) -> &TypeDeclaration<'a> { + self.base.base() + } + + fn implemented_interfaces(&self) -> &Vec> { + self.base.implemented_interfaces() + } + + fn methods(&self) -> &Vec> { + self.base.methods() + } + + fn properties(&self) -> &Vec> { + self.base.properties() + } + + fn events(&self) -> &Vec { + self.base.events() + } +} + +pub struct GenericInterfaceDeclaration<'a> { + base: InterfaceDeclaration<'a>, +} + +impl GenericInterfaceDeclaration { + pub fn new(metadata: *mut c_void, token: mdToken) -> Self { + Self { + base: InterfaceDeclaration::new_with_kind(DeclarationKind::GenericInterface, metadata, token) + } + } + + pub fn number_of_generic_parameters(&self) -> usize { + let mut count = 0; + let enumerator = std::ptr::null_mut(); + let base = self.base.base.base(); + debug_assert!( + imeta_data_import2::enum_generic_params( + base.metadata, enumerator, base.token, None, None, None, + ).is_ok() + ); + debug_assert!( + imeta_data_import2::count_enum(base.metadata, enumerator, &mut count).is_ok() + ); + + return count; + } + + pub fn id(&self) -> GUID { + self.base.id() + } +} + +impl<'a> BaseClassDeclarationImpl for GenericInterfaceDeclaration<'a> { + fn base(&self) -> &TypeDeclaration<'a> { + self.base.base() + } + + fn implemented_interfaces(&self) -> &Vec> { + self.base.implemented_interfaces() + } + + fn methods(&self) -> &Vec> { + self.base.methods() + } + + fn properties(&self) -> &Vec> { + self.base.properties() + } + + fn events(&self) -> &Vec { + self.base.events() + } +} + +impl<'a> Declaration for GenericInterfaceDeclaration { + fn name<'a>(&self) -> Cow<'a, str> { + self.base.name() + } + + fn full_name<'a>(&self) -> Cow<'a, str> { + self.base.full_name() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind() + } +} + + +pub struct GenericInterfaceInstanceDeclaration<'a> { + base: InterfaceDeclaration<'a>, + closed_metadata: *mut c_void, + closed_token: mdTypeSpec, +} + +impl GenericInterfaceInstanceDeclaration { + pub fn new(open_metadata: *mut c_void, open_token: mdTypeDef, closed_metadata: *mut c_void, closed_token: mdTypeSpec) -> Self { + debug_assert!(!closed_metadata.is_null()); + debug_assert!(enums::type_from_token(closed_token) == CorTokenType::mdtTypeSpec); + debug_assert!(closed_token != mdTypeSpecNil); + + Self { + base: InterfaceDeclaration::new_with_kind( + DeclarationKind::GenericInterfaceInstance, open_metadata, open_token, + ), + closed_metadata, + closed_token, + } + } + pub fn id(&self) -> GUID { + return GenericInstanceIdBuilder::generate_id(self); + } +} + +impl<'a> BaseClassDeclarationImpl for GenericInterfaceInstanceDeclaration { + fn base(&self) -> &TypeDeclaration<'a> { + self.base.base() + } + + fn implemented_interfaces(&self) -> &Vec> { + self.base.implemented_interfaces() + } + + fn methods(&self) -> &Vec> { + self.base.methods() + } + + fn properties(&self) -> &Vec> { + self.base.properties() + } + + fn events(&self) -> &Vec> { + self.base.events() + } +} + +impl<'a> Declaration for GenericInterfaceInstanceDeclaration { + fn name<'a>(&self) -> Cow<'a, str> { + self.base.name() + } + + fn full_name<'a>(&self) -> Cow<'a, str> { + let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; + let mut signature_size = 0; + debug_assert!( + imeta_data_import2::get_type_spec_from_token( + self.closed_metadata, self.closed_token, signature.as_mut_ptr(), &mut signature_size, + ).is_ok() + ); + Signature::to_string( + self.closed_metadata, signature.as_ptr(), + ).into() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind() + } +} \ No newline at end of file diff --git a/core/src/metadata/declarations/method_declaration.rs b/core/src/metadata/declarations/method_declaration.rs new file mode 100644 index 0000000..bf6f615 --- /dev/null +++ b/core/src/metadata/declarations/method_declaration.rs @@ -0,0 +1,192 @@ +use crate::{ + bindings::enums, + bindings::helpers, + bindings::imeta_data_import2, + metadata::declarations::declaration::{Declaration, DeclarationKind}, + metadata::declarations::type_declaration::TypeDeclaration, + metadata::signature::Signature, + prelude::* +}; +use crate::enums::CorCallingConvention; +use crate::metadata::com_helpers::get_unary_custom_attribute_string_value; +use crate::metadata::declarations::parameter_declaration::ParameterDeclaration; + +pub struct MethodDeclaration <'a> { + base: TypeDeclaration<'a>, + parameters: Vec>, +} + +const OVERLOAD_ATTRIBUTE: &'static str = "Windows.Foundation.Metadata.OverloadAttribute"; +const DEFAULT_OVERLOAD_ATTRIBUTE: &'static str ="Windows.Foundation.Metadata.DefaultOverloadAttribute"; + +impl MethodDeclaration { + pub fn new(metadata: *mut c_void, token: mdMethodDef) -> Self { + debug_assert!(!metadata.is_null()); + debug_assert!(enums::type_from_token(token) == CorTokenType::mdtMethodDef as u32); + assert!(token != mdMethodDefNil); + + + let mut signature = std::ptr::null_mut(); + let mut sig = &signature; + let mut signature_size: ULONG = 0; + + debug_assert!( + imeta_data_import2::get_method_props( + metadata, token, None, None, None, + None,None,Some(sig as *mut const* u8), Some(&mut signature_size), + None,None + ).is_ok() + ); + + + /* + #if _DEBUG + PCCOR_SIGNATURE startSignature{ signature }; +#endif + */ + + + if helpers::cor_sig_uncompress_calling_conv(signature as _) == CorCallingConvention::ImageCeeCsCallconvGeneric as u32 { + std::unimplemented!() + } + + let mut arguments_count = { helpers::cor_sig_uncompress_data(signature) }; + + let return_type = Signature::consumeType(signature); + + let mut parameters: Vec = Vec::new(); + let mut parameter_enumerator = std::ptr::null_mut(); + let enumerator = &mut parameter_enumerator; + let mut parameters_count: ULONG = 0; + let mut parameter_tokens: Vec = vec![0; 1024]; + + debug_assert!(imeta_data_import2::enum_params(metadata, enumerator, token, parameter_tokens.as_mut_ptr(), parameter_tokens.len() as u32,&mut parameters_count).is_ok()); + debug_assert!(parameters_count < (parameter_tokens.len() - 1) as u32); + + imeta_data_import2::close_enum(metadata, parameter_enumerator); + + let mut start_index = 0_usize; + + if arguments_count + 1 == parameters_count { + start_index += 1; + } + + for i in start_index..parameters_count { + let sig_type = Signature::consume_type(signature); + parameters.push( + ParameterDeclaration::new( + metadata, parameter_tokens[i], sig_type + ) + ) + } + + ASSERT(startSignature + signatureSize == signature); + + Self { + base: TypeDeclaration::new(DeclarationKind::Method, metadata, token), + parameters + } + } + + pub fn is_initializer(&self) -> bool{ + let mut full_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + let mut method_flags = 0; + assert!( + imeta_data_import2::get_method_props( + self.base.metadata, self.base.token, + None, + Some(full_name_data.as_mut_ptr()), Some(full_name_data.len() as u32), + None, Some(&mut method_flags), None, None, None, None + ).is_ok() + ); + + helpers::is_md_instance_initializer_w(method_flags, full_name_data.as_ptr()) + } + + pub fn is_static(&self) -> bool { + let mut method_flags = 0; + assert!( + imeta_data_import2::get_method_props( + self.base.metadata, self.base.token, None, + None, None, None,Some(&mut method_flags), + None, None, None, None + ).is_ok() + ); + helpers::is_md_static(method_flags) + } + + pub fn is_sealed(&self) -> bool { + let mut method_flags = 0; + assert!( + imeta_data_import2::get_method_props( + self.base.metadata, self.base.token, None, + None, None, None,Some(&mut method_flags), + None, None, None, None + ).is_ok() + ); + helpers::is_md_static(method_flags) || helpers::is_md_final(method_flags) + } + + pub fn parameters(&self) -> &Vec { + &self.parameters + } + + pub fn number_of_parameters(&self) -> usize{ + self.parameters.len() + } + + pub fn overload_name<'a>(&self) ->&'a str { + get_unary_custom_attribute_string_value(self.base.metadata, self.base.token, OVERLOAD_ATTRIBUTE) + } + + pub fn is_default_overload(&self) -> bool { + let data = OsString::from(DEFAULT_OVERLOAD_ATTRIBUTE).to_wide(); + let get_attribute_result = imeta_data_import2::get_custom_attribute_by_name( + self.base.metadata, self.base.token, Some(data.as_ptr()),None,None + ); + debug_assert!(get_attribute_result.is_ok()); +return get_attribute_result.0 == 0; +} +} + +impl Declaration for MethodDeclaration { + fn is_exported(&self) -> bool { + let mut method_flags: DWORD = 0; + debug_assert!( + imeta_data_import2::get_method_props( + self.base.metadata, self.base.token, None, None, None, None, Some(&mut method_flags), None, None, None, None + ).is_ok() + ); + + if !(helpers::is_md_public(method_flags) || helpers::is_md_family(method_flags) || helpers::is_md_fam_orassem(method_flags)) { + return false; + } + + if helpers::is_md_special_name(method_flags) { + return false; + } + + return true; + } + + fn name<'a>(&self) -> &'a str { + self.full_name() + } + + fn full_name<'a>(&self) -> &'a str { + let mut name_length = 0; + let mut data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + debug_assert!( + imeta_data_import2::get_method_props( + self.base.metadata, self.base.token, None, Some(data.as_mut_ptr()), Some(data.len() as u32), + Some(&mut name_length), None, None, None, None, None + ).is_ok() + ); + data.resize(name_length as usize, 0); + OsString::from_wide(data.as_slice()).to_string_lossy().as_ref() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind + } +} diff --git a/core/src/metadata/declarations/mod.rs b/core/src/metadata/declarations/mod.rs index 4e92ff0..7b51a98 100644 --- a/core/src/metadata/declarations/mod.rs +++ b/core/src/metadata/declarations/mod.rs @@ -1,4 +1,15 @@ pub mod declaration; pub mod type_declaration; pub mod field_declaration; -pub mod enum_declaration; \ No newline at end of file +pub mod enum_declaration; +pub mod base_class_declaration; +pub mod interface_declaration; +pub mod method_declaration; +pub mod property_declaration; +pub mod event_declaration; +pub mod class_declaration; +pub mod parameter_declaration; +pub mod delegate_declaration; +pub mod namespace_declaration; +pub mod struct_declaration; +pub mod struct_field_declaration; \ No newline at end of file diff --git a/core/src/metadata/declarations/namespace_declaration.rs b/core/src/metadata/declarations/namespace_declaration.rs new file mode 100644 index 0000000..27058b5 --- /dev/null +++ b/core/src/metadata/declarations/namespace_declaration.rs @@ -0,0 +1,47 @@ +use crate::metadata::declarations::type_declaration::TypeDeclaration; +use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; +use std::option::Option::Some; + +pub struct NamespaceDeclaration<'a> { + base: TypeDeclaration<'a>, + children: Vec<&'a str>, + full_name: &'a str +} + + +impl Declaration for NamespaceDeclaration { + fn name(&self) -> String { + let mut fully_qualified_name = self.full_name().to_owned(); + if let Some(index) = fully_qualified_name.find(".") { + fully_qualified_name = fully_qualified_name.chars().skip(index + 1).collect() + } + return fully_qualified_name; + } + + fn full_name<'a>(&self) -> &'a str { + self.full_name + } + + fn kind(&self) -> DeclarationKind { + self.base.kind + } +} + +impl NamespaceDeclaration { + pub fn new(full_name: &str) -> Self { + // ASSERT(fullName); + + Self { + base: TypeDeclaration::new( + DeclarationKind::Namespace, + std::ptr::null_mut(), + std::ptr::null_mut() + ), + children: Vec::new(), + full_name + } + } + pub fn children<'a>(&self) -> &[&'a str] { + self.children.as_slice() + } +} \ No newline at end of file diff --git a/core/src/metadata/declarations/parameter_declaration.rs b/core/src/metadata/declarations/parameter_declaration.rs new file mode 100644 index 0000000..1a179af --- /dev/null +++ b/core/src/metadata/declarations/parameter_declaration.rs @@ -0,0 +1,55 @@ +use crate::prelude::*; +use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; +use crate::metadata::declarations::type_declaration::TypeDeclaration; +use crate::bindings::{ + enums, helpers, imeta_data_import2 +}; +use crate::enums::CorElementType; + + +pub struct ParameterDeclaration<'a> { + base: TypeDeclaration<'a>, + parameter_type: PCCOR_SIGNATURE +} + +impl ParameterDeclaration { + pub fn new(metadata: *mut c_void, token: mdParamDef, sig_type: PCCOR_SIGNATURE)-> Self { + + debug_assert!(!metadata.is_null()); + debug_assert!(enums::type_from_token(token) == CorTokenType::mdtParamDef as u32); + debug_assert!(token != mdParamDefNil); + + Self { + base: TypeDeclaration::new( + DeclarationKind::Parameter, metadata, token + ), + parameter_type: sig_type + } + } + pub fn is_out(&self) -> bool { + helpers::cor_sig_uncompress_token(self.parameter_type) == CorElementType::ElementTypeByref as u32 + } +} + +impl Declaration for ParameterDeclaration { + + fn name<'a>(&self) -> &'a str { + self.full_name() + } + + fn full_name<'a>(&self) -> &'a str { + let mut full_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + let mut length = 0; + assert!(imeta_data_import2::get_param_props(self.metadata, self.token, + None,None, + Some(full_name_data.as_mut_ptr()), Some(full_name_data.len() as u32), +Some(&mut length),None,None,None,None + ).is_ok()); + full_name_data.resize(length as usize, 0); + OsString::from_wide(name.as_slice()).to_string_lossy().as_ref() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind + } +} \ No newline at end of file diff --git a/core/src/metadata/declarations/property_declaration.rs b/core/src/metadata/declarations/property_declaration.rs new file mode 100644 index 0000000..bc5c1fc --- /dev/null +++ b/core/src/metadata/declarations/property_declaration.rs @@ -0,0 +1,148 @@ +use crate::{ + bindings::enums, + bindings::helpers, + bindings::imeta_data_import2, + metadata::declarations::declaration::{Declaration, DeclarationKind}, + metadata::declarations::field_declaration::FieldDeclaration, + metadata::declarations::method_declaration::MethodDeclaration, + prelude::* +}; +use crate::enums::CorCallingConvention; + +pub struct PropertyDeclaration <'a>{ + base: FieldDeclaration<'a>, + getter: MethodDeclaration<'a>, + setter: Option> +} + +impl <'a> Declaration<'a> for PropertyDeclaration { + fn is_exported(&self) -> bool { + let mut property_flags = 0; + debug_assert!( + imeta_data_import2::get_property_props( + self.base.metadata, self.base.token, None, None, None, None, + Some(&mut property_flags), None, None, None, None, None, + None, None, None, None, None + ).is_ok() + ); + + if helpers::is_pr_special_name(property_flags) { + return false + } + true + } + + fn name<'a>(&self) -> &'a str { + self.base.name() + } + + fn full_name<'a>(&self) -> &'a str { + let mut full_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + let mut name_length = 0; + debug_assert!( + imeta_data_import2::get_property_props( + self.base.metadata, + self.base.token, + None, + Some(full_name_data.as_mut_ptr()), + Some(full_name_data.len() as u32), + Some(&mut name_length), + None, None, None, None, None, None, None, + None, None, None, None + ).is_ok() + ); + full_name_data.resize(name_length as usize, 0); + OsString::from_wide(full_name_data.as_slice()).to_string_lossy().as_ref() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind + } +} + +impl PropertyDeclaration { + + fn make_getter(metadata: *mut c_void, token : mdProperty) -> MethodDeclaration { + let mut getter_token = mdTokenNil; + debug_assert!( + imeta_data_import2::get_property_props( + metadata, token, None, None, None, + None, None, None, None,None, + None,None,None,Some(&mut getter_token), + None,None, None + ).is_ok() + ); + + debug_assert!(getter_token != mdMethodDefNil); + + MethodDeclaration::new( + metadata, getter_token + ) + } + + fn make_setter(metadata: *mut c_void, token : mdProperty) -> Option{ + let mut setter_token = mdTokenNil; + + debug_assert!( + imeta_data_import2::get_property_props( + metadata, token, None, None, None, + None, None, None,None,None, + None, None, Some(&mut setter_token), None, + None, None,None + ).is_ok() + ); + + + if setterToken == mdMethodDefNil { + return None; + } + + + return Some(MethodDeclaration::new(metadata, setter_token)); + } + + pub fn new(metadata: *mut c_void, token: mdProperty) -> Self{ + debug_assert!(metadata); + debug_assert!(enums::type_from_token(token) == CorTokenType::mdtProperty as u32); + debug_assert(token != mdPropertyNil); + Self { + base: FieldDeclaration::new( + DeclarationKind::Property, metadata, token + ), + getter: PropertyDeclaration::make_getter( + metadata, token + ), + setter: PropertyDeclaration::make_setter(metadata, token) + } + } + + pub fn is_static(&self) -> bool { + let mut signature = vec![0_u8;1]; + let mut signature_count = 0; + + debug_assert!( + imeta_data_import2::get_property_props( + self.base.metadata, self.base.token, None, None, None, + None, None, Some(signature.as_mut_ptr() as _), Some(&mut signature_count), + None, None, None, None, None, None, + None, None + ) .is_ok() + ); + + debug_assert!(signature_count > 0); + + signature[0] & CorCallingConvention::ImageCeeCsCallconvGenericinst == 0 + } + + pub fn is_sealed(&self) -> bool { + self.getter.is_sealed() + } + + pub fn getter(&self) -> &MethodDeclaration { + &self.getter + } + + pub fn setter<'a>(&self) -> Option<&MethodDeclaration<'a>> { + self.setter.as_ref() + } +} \ No newline at end of file diff --git a/core/src/metadata/declarations/struct_declaration.rs b/core/src/metadata/declarations/struct_declaration.rs new file mode 100644 index 0000000..4aa2b8b --- /dev/null +++ b/core/src/metadata/declarations/struct_declaration.rs @@ -0,0 +1,66 @@ +use crate::prelude::*; +use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; +use crate::metadata::declarations::type_declaration::TypeDeclaration; +use crate::bindings::imeta_data_import2; +use crate::metadata::declarations::struct_field_declaration::StructFieldDeclaration; + +pub struct StructDeclaration<'a> { + base: TypeDeclaration<'a>, + fields: Vec>, +} + +impl Declaration for StructDeclaration { + fn name<'a>(&self) -> &'a str { + self.base.name() + } + + fn full_name<'a>(&self) -> &'a str { + self.base.full_name() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind + } +} + +impl StructDeclaration { + pub fn new(metadata: *mut c_void, token: mdTypeDef, + ) -> Self { + Self { + base: TypeDeclaration::new( + DeclarationKind::Struct, metadata, token, + ), + fields: StructDeclaration::make_field_declarations(metadata, token), + } + } + + pub fn size(&self) -> usize { + self.fields.len() + } + + fn make_field_declarations(metadata: *mut c_void, token: mdTypeDef) -> Vec { + let enumerator = std::ptr::null_mut(); + let mut count = 0; + let mut tokens: Vec = vec![0; 1024]; + debug_assert!( + imeta_data_import2::enum_fields( + metadata, enumerator, token, tokens.as_mut_ptr(), tokens.len(), &mut count, + ).is_ok() + ); + + debug_assert!(count < tokens.len() - 1); + + imeta_data_import2::close_enum(metadata, enumerator); + + let mut result = Vec::new(); + + for i in 0..count { + result.push( + StructFieldDeclaration::new(metadata, tokens[i]) + ) + } + + + return result; + } +} \ No newline at end of file diff --git a/core/src/metadata/declarations/struct_field_declaration.rs b/core/src/metadata/declarations/struct_field_declaration.rs new file mode 100644 index 0000000..5d048b5 --- /dev/null +++ b/core/src/metadata/declarations/struct_field_declaration.rs @@ -0,0 +1,54 @@ +use crate::prelude::*; +use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; +use crate::metadata::declarations::field_declaration::FieldDeclaration; +use crate::bindings::{imeta_data_import2, helpers}; + +pub struct StructFieldDeclaration<'a> { + base: FieldDeclaration<'a>, +} + +impl Declaration for StructFieldDeclaration { + fn name<'a>(&self) -> &'a str { + self.base.name() + } + + fn full_name<'a>(&self) -> &'a str { + self.base.full_name() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind + } +} + +impl StructFieldDeclaration { + pub fn new(metadata: *mut c_void, token: mdFieldDef) -> Self { + Self { + base: FieldDeclaration::new( + DeclarationKind::StructField, + metadata, + token, + ) + } + } + + pub fn type_(&self) -> PCCOR_SIGNATURE { + let mut signature = vec![0_u8; MAX_IDENTIFIER_LENGTH]; + let mut signature_size = 0; + + debug_assert!( + imeta_data_import2::get_field_props( + self.base.metadata, self.base.token, None, None, None, + None, None, Some(signature.as_mut_ptr()), Some(&mut signature_size), + None, None, None, + ).is_ok() + ); + signature.resize(signature_size, 0); + let header = helpers::cor_sig_uncompress_data(signature.as_mut_ptr()); + debug_assert!( + header == CorCallingConvention::ImageCeeCsCallconvField + ); + + return signature; + } +} \ No newline at end of file diff --git a/core/src/metadata/declarations/type_declaration.rs b/core/src/metadata/declarations/type_declaration.rs index cc339ad..c003cb3 100644 --- a/core/src/metadata/declarations/type_declaration.rs +++ b/core/src/metadata/declarations/type_declaration.rs @@ -1,79 +1,91 @@ -use crate::prelude::*; -use super::declaration::{Declaration, DeclarationKind}; -use crate::bindings::{ - imeta_data_import2, - helpers, - enums +use crate::{ + prelude::*, + bindings::{ + imeta_data_import2, + helpers, + enums, + }, }; +use super::declaration::{Declaration, DeclarationKind}; use std::marker; use std::ffi::{OsString}; +use std::borrow::Cow; + + -pub struct TypeDeclaration <'a>{ - pub kind: DeclarationKind, - pub metadata: *const c_void, - pub token: mdTypeDef, - _marker: marker::PhantomData<&'a *const c_void> +pub struct TypeDeclaration<'a> { + pub kind: DeclarationKind, + pub metadata: *mut c_void, + pub token: mdTypeDef, + _marker: marker::PhantomData<&'a *const c_void>, } impl Declaration for TypeDeclaration { - fn kind(&self) -> DeclarationKind{ - self.kind - } + fn is_exported(&self) -> bool { + let mut flags: DWORD = 0; + debug_assert!( + imeta_data_import2::get_type_def_props( + self.metadata, self.token, None, None, None, Some(&mut flags), None, + ).is_ok() + ); - fn is_exported(&self) -> bool { - let mut flags: DWORD = 0; - assert( - imeta_data_import2::get_type_def_props( - self.token, 0, 0,0, &mut flags, 0 - ).is_ok() - ); + if !helpers::is_td_public(flags) || helpers::is_td_special_name(flags) { + return false; + } - if !helpers::is_td_public(flags) || helpers::is_td_special_name(flags) { - return false; - } + return true; + } - return true; - } - - fn name<'b>(&self) -> &'b str { - let mut name = self.full_name(); + fn name<'a>(&self) -> Cow<'a, str> { + let mut name = self.full_name().to_string(); + let back_tick_index = name.find('`'); + if let Some(index) = back_tick_index { + name = name + .chars() + .take(0) + .chain( + name.chars().skip(index) + ).collect() + } - // size_t backtickIndex{ fullyQualifiedName.rfind(L"`") }; - // if (backtickIndex != wstring::npos) { - // fullyQualifiedName.erase(backtickIndex); - // } - // - // size_t dotIndex{ fullyQualifiedName.rfind(L".") }; - // if (dotIndex != wstring::npos) { - // fullyQualifiedName.erase(0, dotIndex + 1); - // } + let dot_index = name.find('.'); + if let Some(index) = dot_index { + name = name + .chars() + .take(0) + .chain( + name.chars().skip(index + 1) + ).collect() + } - return name; - } + name.into() + } - fn full_name<'b>(&self) -> &'b str { - let mut full_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + fn full_name<'a>(&self) -> Cow<'a, str> { + let mut full_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; + let length = helpers::get_type_name(self.metadata, self.token, full_name_data.as_mut_ptr(), full_name_data.len() as u32); + OsString::from_wide(&full_name_data[..length]).into() + } - let length = Helpers_Get_Type_Name(self.metadata, self.token, full_name_data.as_mut_ptr(), full_name_data.len()); - full_name_data.resize(length as usize, 0); - OsString::from_wide(name.as_slice()) - } + fn kind(&self) -> DeclarationKind { + self.kind + } } impl TypeDeclaration { - pub fn new(kind: DeclarationKind, metadata: *const c_void, token: mdTypeDef) -> Self { - let value = Self { - kind, - metadata, - token, - _marker: marker::PhantomData - }; + pub fn new(kind: DeclarationKind, metadata: *mut c_void, token: mdTypeDef) -> Self { + let value = Self { + kind, + metadata, + token, + _marker: marker::PhantomData, + }; - assert!(value.metadata.is_not_null()); - assert!(enums::type_from_token(value.token) == mdtTypeDef); - assert!(value.token != mdTypeDefNil); - value - } + assert!(!value.metadata.is_null()); + assert!(enums::type_from_token(value.token) == CorTokenType::mdtTypeDef as u32); + assert!(value.token != mdTypeDefNil); + value + } } \ No newline at end of file diff --git a/core/src/metadata/generic_instance_id_builder.rs b/core/src/metadata/generic_instance_id_builder.rs new file mode 100644 index 0000000..06d8919 --- /dev/null +++ b/core/src/metadata/generic_instance_id_builder.rs @@ -0,0 +1,156 @@ +use crate::prelude::*; +use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; +use crate::bindings::helpers; +use crate::metadata::meta_data_reader::MetadataReader; +pub struct GenericInstanceIdBuilder {} + +pub use crate::bindings::rometadataresolution; +use core_bindings::GUID; +use crate::metadata::declarations::class_declaration::ClassDeclaration; +use std::sync::Arc; + + +impl GenericInstanceIdBuilder { + extern "C" fn locator_impl(name: PCWSTR, builder: *mut IRoSimpleMetaDataBuilder) -> windows::HRESULT { + let declaration = MetadataReader::find_by_name(name); + debug_assert!(declaration.is_some()); + + if let Some(declaration) = declaration { + match declaration.kind() { + DeclarationKind::Class => { + let mut classDeclaration = declaration + .as_any() + .downcast_ref::() + .unwrap(); + + let defaultInterface = classDeclaration.default_interface(); + let defaultInterfaceId = defaultInterface.id(); + debug_assert!( + + ); + ASSERT_SUCCESS(builder.SetRuntimeClassSimpleDefault(name, defaultInterface.fullName().data(), &defaultInterfaceId)); + return S_OK; + } + DeclarationKind::Interface => {} + DeclarationKind::GenericInterface => {} + DeclarationKind::GenericInterfaceInstance => {} + DeclarationKind::Enum => {} + DeclarationKind::EnumMember => {} + DeclarationKind::Struct => {} + DeclarationKind::StructField => {} + DeclarationKind::Delegate => {} + DeclarationKind::GenericDelegate => {} + DeclarationKind::GenericDelegateInstance => {} + DeclarationKind::Event => {} + DeclarationKind::Property => {} + DeclarationKind::Method => {} + DeclarationKind::Parameter => {} + } + } + DeclarationKind kind{ declaration->kind() }; + switch (kind) { + case DeclarationKind::Class: { + ClassDeclaration* classDeclaration{ static_cast(declaration.get()) }; + const InterfaceDeclaration& defaultInterface{ classDeclaration->defaultInterface() }; + IID defaultInterfaceId = defaultInterface.id(); + ASSERT_SUCCESS(builder.SetRuntimeClassSimpleDefault(name, defaultInterface.fullName().data(), &defaultInterfaceId)); + return S_OK; + } + + case DeclarationKind::Interface: { + InterfaceDeclaration* interfaceDeclaration{ static_cast(declaration.get()) }; + ASSERT_SUCCESS(builder.SetWinRtInterface(interfaceDeclaration->id())); + return S_OK; + } + + case DeclarationKind::GenericInterface: { + GenericInterfaceDeclaration* genericInterfaceDeclaration{ static_cast(declaration.get()) }; + ASSERT_SUCCESS(builder.SetParameterizedInterface(genericInterfaceDeclaration->id(), genericInterfaceDeclaration->numberOfGenericParameters())); + return S_OK; + } + + case DeclarationKind::Enum: { + EnumDeclaration* enumDeclaration{ static_cast(declaration.get()) }; + ASSERT_SUCCESS(builder.SetEnum(enumDeclaration->fullName().data(), Signature::toString(nullptr, enumDeclaration->type()).data())); + return S_OK; + } + + case DeclarationKind::Struct: { + StructDeclaration* structDeclaration{ static_cast(declaration.get()) }; + + vector fieldNames; + for (const StructFieldDeclaration& field : *structDeclaration) { + fieldNames.push_back(Signature::toString(field._metadata.Get(), field.type())); + } + + vector fieldNamesW; + for (wstring& fieldName : fieldNames) { + fieldNamesW.push_back(const_cast(fieldName.data())); + } + + ASSERT_SUCCESS(builder.SetStruct(structDeclaration->fullName().data(), structDeclaration->size(), fieldNamesW.data())); + return S_OK; + } + + case DeclarationKind::Delegate: { + DelegateDeclaration* delegateDeclaration{ static_cast(declaration.get()) }; + ASSERT_SUCCESS(builder.SetDelegate(delegateDeclaration->id())); + return S_OK; + } + + case DeclarationKind::GenericDelegate: { + GenericDelegateDeclaration* genericDelegateDeclaration{ static_cast(declaration.get()) }; + ASSERT_SUCCESS(builder.SetParameterizedDelegate(genericDelegateDeclaration->id(), genericDelegateDeclaration->numberOfGenericParameters())); + return S_OK; + } + + default: + ASSERT_NOT_REACHED(); + } + } + + pub fn generate_id(declaration: &dyn Declaration){ + let declaration_full_name = declaration.full_name(); + let mut name_ref = windows::HSTRING::from(declaration_full_name); + let cap = vec![0_u16;MAX_IDENTIFIER_LENGTH]; + let mut nameParts = windows::HSTRING::from_wide(cap.as_slice()); + let mut name_parts_ref = &mut nameParts.as_mut_ptr(); + let mut namePartsCount = 0; + debug_assert!( + rometadataresolution::ro_parse_type_name( + name_ref, &mut namePartsCount, name_parts_ref + ).is_ok() + ); + + let mut namePartsW = vec![0_u16; 128]; + debug_assert!( + namePartsCount < namePartsW.len() as u32 + ); + + for i in 0..namePartsCount { + namePartsCount[i] = helpers::windows_get_string_raw_buffer(nameParts.as_wide()[i],None) + } + + + let mut guid = GUID::default(); + debug_assert!( + rometadataresolution::ro_get_parameterized_type_instance_iid( + namePartsCount, namePartsW.as_mut_ptr(), rometadataresolution::ro_locator( + Option(GenericInstanceIdBuilder::locator_impl) + ), &mut guid, None + ) + ); + + /* + for (size_t i = 0; i < namePartsCount; ++i) { + ASSERT_SUCCESS(WindowsDeleteString(nameParts[i])); + } + */ + + //CoTaskMemFree(nameParts); + + return guid; + } + + // HRESULT locatorImpl(PCWSTR name, IRoSimpleMetaDataBuilder& builder); +} \ No newline at end of file diff --git a/core/src/metadata/meta_data_reader.rs b/core/src/metadata/meta_data_reader.rs new file mode 100644 index 0000000..9273380 --- /dev/null +++ b/core/src/metadata/meta_data_reader.rs @@ -0,0 +1,138 @@ +use crate::prelude::*; +use std::sync::Arc; +use crate::metadata::declarations::declaration::Declaration; +use crate::metadata::declarations::namespace_declaration::NamespaceDeclaration; +use crate::metadata::declarations::enum_declaration::EnumDeclaration; +use crate::metadata::declarations::d +use crate::metadata::declarations::delegate_declaration::{GenericDelegateDeclaration, InterfaceDeclaration, DelegateDeclaration}; +use crate::bindings::{rometadataresolution, imeta_data_import2, helpers, enums}; +use windows::HSTRING; +use crate::metadata::declarations::declaration::DeclarationKind::GenericInterfaceInstance; +use crate::metadata::declarations::struct_declaration::StructDeclaration; +use crate::metadata::declarations::class_declaration::ClassDeclaration; + +const WINDOWS: &'static src = "Windows"; +const SYSTEM_ENUM: &'static src = "System.Enum"; +const SYSTEM_VALUETYPE: &'static src = "System.ValueType"; +const SYSTEM_MULTICASTDELEGATE: &'static src = "System.MulticastDelegate"; + +pub struct MetadataReader {} + +impl MetadataReader { + pub fn find_by_name(full_name:&str) -> Option>{ + if full_name.is_empty() { + return Some( + Arc::new( + NamespaceDeclaration::new("") + ) + ) + } + let mut metadata = std::ptr::null_mut(); + let meta = &mut metadata; + let mut token = mdTokenNil; + let mut full_name_hstring = HSTRING::from(full_name); + let get_metadata_file_result = rometadataresolution::ro_get_meta_data_file( + &mut full_name_hstring, None, None, Some(meta), Some(&mut token) + ); + + if get_metadata_file_result.is_err() { + if get_metadata_file_result == RO_E_METADATA_NAME_IS_NAMESPACE { + return Some( + Arc::new(NamespaceDeclaration::new(full_name)) + ) + } + return None + } + + let mut flags = 0; + let mut parent_token = mdTokenNil; + debug_assert!(imeta_data_import2::get_type_def_props( + metadata, token, None, None, None, Some(&mut flags), Some(&mut parent_token) + ).is_ok()); + + + + if helpers::is_td_class(flags) { + let mut parent_name = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + + match enums::type_from_token(parent_token) { + mdtTypeDef => { + debug_assert!( + imeta_data_import2::get_type_def_props( + metadata,parent_token, Some(parent_name.as_mut_ptr()), Some(parent_name.len()), + None, None, None + ).is_ok() + ); + } + mdtTypeRef => { + debug_assert!( + imeta_data_import2::get_type_ref_props( + metadata, parent_name, None, Some(parent_name.as_mut_ptr()), Some(parent_name.len()), None + ).is_ok() + ) + } + _=> { + std::unreachable!() + } + } + + let mut parent_name_string = OsString::from_wide(parent_name.as_slice()).to_string_lossy().as_ref(); + + if parent_name_string == SYSTEM_ENUM { + return Some( + Arc::new( + EnumDeclaration::new(metadata, token) + ) + ) + } + + if parent_name_string == SYSTEM_VALUETYPE { + return Some( + Arc::new( + StructDeclaration::new(metadata, token) + ) + ) + } + + if parent_name_string == SYSTEM_MULTICASTDELEGATE { + if full_name.contains("`"){ + return Some( + Arc::new( + GenericDelegateDeclaration::new(metadata, token) + ) + ) + }else { + return Some( + Arc::new( + DelegateDeclaration::new(metadata, token) + ) + ) + } + } + + return Some( + Arc::new( + ClassDeclaration::new(metadata, token) + ) + ) + } + + if helpers::is_td_interface(flags) { + return if full_name.contains("`") { + Some( + Arc::new( + GenericInterfaceDeclaration::new(metadata, token) + ) + ) + } else { + Some( + Arc::new( + InterfaceDeclaration::new(metadata, token) + ) + ) + } + } + + std::unreachable!(); + } +} \ No newline at end of file diff --git a/core/src/metadata/mod.rs b/core/src/metadata/mod.rs index 599bbc0..3ded577 100755 --- a/core/src/metadata/mod.rs +++ b/core/src/metadata/mod.rs @@ -1,10 +1,6 @@ pub mod com_helpers; -pub mod token_type; - -pub struct MetadataReader {} - -impl MetadataReader { - pub fn find_by_name(&self){ - - } -} \ No newline at end of file +pub mod declarations; +pub mod signature; +pub mod declaration_factory; +pub mod generic_instance_id_builder; +pub mod meta_data_reader; diff --git a/core/src/metadata/signature.rs b/core/src/metadata/signature.rs new file mode 100644 index 0000000..a4b87c3 --- /dev/null +++ b/core/src/metadata/signature.rs @@ -0,0 +1,151 @@ +use crate::prelude::*; +use crate::bindings::helpers; +use crate::metadata::enums::CorElementType; + +pub struct Signature {} + +impl Signature { + pub fn consume_type(signature: PCCOR_SIGNATURE) -> PCCOR_SIGNATURE { + let start = signature; + let element_type = helpers::cor_sig_uncompress_element_type(signature); + match element_type { + CorElementType::ElementTypeVoid | + CorElementType::ElementTypeBoolean | + CorElementType::ElementTypeChar | + CorElementType::ElementTypeI1 | + CorElementType::ElementTypeU1 | + CorElementType::ElementTypeI2 | + CorElementType::ElementTypeU2 | + CorElementType::ElementTypeI4 | + CorElementType::ElementTypeU4 | + CorElementType::ElementTypeI8 | + CorElementType::ElementTypeU8 | + CorElementType::ElementTypeR4 | + CorElementType::ElementTypeR8 | + CorElementType::ElementTypeString => start, + CorElementType::ElementTypeValuetype => { + helpers::cor_sig_uncompress_token(signature); + start + } + CorElementType::ElementTypeClass => { + helpers::cor_sig_uncompress_token(signature); + start + } + CorElementType::ElementTypeObject => start, + CorElementType::ElementTypeSzarray => { + Signature::consume_type(signature); + start + } + CorElementType::ElementTypeVar =>{ + helpers::cor_sig_uncompress_data(signature); + start + } + CorElementType::ElementTypeGenericinst =>{ + helpers::cor_sig_uncompress_element_type(signature); + helpers::cor_sig_uncompress_token(signature); + + let generic_arguments_count = helpers::cor_sig_uncompress_data(signature); + for i in 0..generic_arguments_count { + Signature::consume_type(signature) + } + start + } + CorElementType::ElementTypeByref => { + Signature::consume_type(signature); + start + } + _ => { + std::unreachable!() + } + } + } + + pub fn to_string<'a>(metadata: *mut c_void, signature: PCCOR_SIGNATURE) -> &'a str { + let element_type = helpers::cor_sig_uncompress_element_type(signature); + match element_type { + CorElementType::ElementTypeVoid => "Void", + CorElementType::ElementTypeBoolean => "Boolean", + CorElementType::ElementTypeChar => "Char16", + CorElementType::ElementTypeI1 => "Int8", + CorElementType::ElementTypeU1 => "UInt8", + CorElementType::ElementTypeI2 => "Int16", + CorElementType::ElementTypeU2 => "UInt16", + CorElementType::ElementTypeI4 => "Int32", + CorElementType::ElementTypeU4 => "UInt32", + CorElementType::ElementTypeI8 => "Int64", + CorElementType::ElementTypeU8 => "UInt64", + CorElementType::ElementTypeR4 => "Single", + CorElementType::ElementTypeR8 => "Double", + CorElementType::ElementTypeString => "String", + CorElementType::ElementTypeValuetype => { + let token = helpers::cor_sig_uncompress_token(signature); + let mut class_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + let length = helpers::get_type_name(metadata, token, class_name_data.as_mut_ptr(), class_name_data.len() as u32); + class_name_data.resize(length as usize, 0); + let class_name = OsString::from_wide(name.as_slice()).to_string_lossy().as_ref(); + if class_name.eq("System.Guid") { + "Guid" + }else { + class_name + } + } + CorElementType::ElementTypeClass => { + let token = helpers::cor_sig_uncompress_token(signature); + let mut class_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + let length = helpers::get_type_name(metadata, token, class_name_data.as_mut_ptr(), class_name_data.len() as u32); + class_name_data.resize(length as usize, 0); + OsString::from_wide(name.as_slice()).to_string_lossy().as_ref() + } + CorElementType::ElementTypeObject => "Object", + CorElementType::ElementTypeSzarray => { + let result = Signature::to_string(metadata, signature); + result.to_owned() + "[]" + } + CorElementType::ElementTypeVar =>{ + let index = helpers::cor_sig_uncompress_data(signature); + let mut result_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + let length = helpers::to_wstring(index, result_data.as_mut_ptr()); + result_data.resize(length, 0); + "Var!".to_owned() + OsString::from_wide(result_data.as_slice()).to_string_lossy().as_ref() + } + CorElementType::ElementTypeGenericinst => { + let generic_type = helpers::cor_sig_uncompress_element_type(signature); + assert(generic_type == CorElementType::ElementTypeClass); + + let token = helpers::cor_sig_uncompress_token(signature); + + + let mut class_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + let length = helpers::get_type_name(metadata, token, class_name_data.as_mut_ptr(), class_name_data.len() as u32); + class_name_data.resize(length as usize, 0); + + + let mut result = OsString::from_wide(name.as_slice()).to_string_lossy().as_ref().to_owned(); + + result += "<"; + + let generic_arguments_count = helpers::cor_sig_uncompress_data(signature); + for i in 0..generic_arguments_count { + let sig_type = Signature::consume_type(signature); + let data = Signature::to_string(metadata, sig_type); + result += data; + if i == generic_arguments_count - 1 { + result += ", "; + } + } + + result += ">"; + + result + } + CorElementType::ElementTypeByref => { + let mut result = "ByRef ".to_owned(); + result += Signature::to_string(metadata, signature); + result + } + _ => { + std::unreachable!() + } + } + } +} \ No newline at end of file diff --git a/core/src/metadata/token_type.rs b/core/src/metadata/token_type.rs deleted file mode 100755 index 5e00072..0000000 --- a/core/src/metadata/token_type.rs +++ /dev/null @@ -1,64 +0,0 @@ -#[derive(Debug, Clone, Copy)] -pub enum CorTokenType { - MdtModule = 0x00000000, - MdtTypeRef = 0x01000000, - MdtTypeDef = 0x02000000, - MdtFieldDef = 0x04000000, - MdtMethodDef = 0x06000000, - MdtParamDef = 0x08000000, - MdtInterfaceImpl = 0x09000000, - MdtMemberRef = 0x0a000000, - MdtCustomAttribute = 0x0c000000, - MdtPermission = 0x0e000000, - MdtSignature = 0x11000000, - MdtEvent = 0x14000000, - MdtProperty = 0x17000000, - MdtModuleRef = 0x1a000000, - MdtTypeSpec = 0x1b000000, - MdtAssembly = 0x20000000, - MdtAssemblyRef = 0x23000000, - MdtFile = 0x26000000, - MdtExportedType = 0x27000000, - MdtManifestResource = 0x28000000, - MdtGenericParam = 0x2a000000, - MdtMethodSpec = 0x2b000000, - MdtGenericParamConstraint = 0x2c000000, - MdtString = 0x70000000, - MdtName = 0x71000000, - MdtBaseType = 0x72000000, - MdtError_ = 1868 -} - -impl From for CorTokenType { - fn from(value: u32) -> Self { - match value { - 0x00000000 => Self::MdtModule, - 0x01000000 => Self::MdtTypeRef, - 0x02000000 => Self::MdtTypeDef, - 0x04000000 => Self::MdtFieldDef, - 0x06000000 => Self::MdtMethodDef, - 0x08000000 => Self::MdtParamDef, - 0x09000000 => Self::MdtInterfaceImpl, - 0x0a000000 => Self::MdtMemberRef, - 0x0c000000 => Self::MdtCustomAttribute, - 0x0e000000 => Self::MdtPermission, - 0x11000000 => Self::MdtSignature, - 0x14000000 => Self::MdtEvent, - 0x17000000 => Self::MdtProperty, - 0x1a000000 => Self::MdtModuleRef, - 0x1b000000 => Self::MdtTypeSpec, - 0x20000000 => Self::MdtAssembly, - 0x23000000 => Self::MdtAssemblyRef, - 0x26000000 => Self::MdtFile, - 0x27000000 => Self::MdtExportedType, - 0x28000000 => Self::MdtManifestResource, - 0x2a000000 => Self::MdtGenericParam, - 0x2b000000 => Self::MdtMethodSpec, - 0x2c000000 => Self::MdtGenericParamConstraint, - 0x70000000 => Self::MdtString, - 0x71000000 => Self::MdtName, - 0x72000000 => Self::MdtBaseType, - _ => Self::MdtError_ - } - } -} \ No newline at end of file diff --git a/core/src/prelude.rs b/core/src/prelude.rs index d093a58..2d06d3c 100644 --- a/core/src/prelude.rs +++ b/core/src/prelude.rs @@ -1,32 +1,47 @@ -pub type ULONG32 = ::std::os::raw::c_uint; -pub type DWORD = ::std::os::raw::c_ulong; -pub type ULONG = ::std::os::raw::c_ulong; -pub type mdScope = LPVOID; -pub type mdToken = ULONG32; -pub type mdModule = mdToken; -pub type mdTypeRef = mdToken; -pub type mdTypeDef = mdToken; -pub type mdFieldDef = mdToken; -pub type mdMethodDef = mdToken; -pub type mdParamDef = mdToken; -pub type mdInterfaceImpl = mdToken; -pub type mdMemberRef = mdToken; -pub type mdCustomAttribute = mdToken; -pub type mdPermission = mdToken; -pub type mdSignature = mdToken; -pub type mdEvent = mdToken; -pub type mdProperty = mdToken; -pub type mdModuleRef = mdToken; -pub type mdAssembly = mdToken; -pub type mdAssemblyRef = mdToken; -pub type mdFile = mdToken; -pub type mdExportedType = mdToken; -pub type mdManifestResource = mdToken; -pub type mdTypeSpec = mdToken; -pub type mdGenericParam = mdToken; -pub type mdMethodSpec = mdToken; -pub type mdGenericParamConstraint = mdToken; -pub type mdString = mdToken; -pub type mdCPToken = mdToken; -pub type RID = ULONG; -pub type LPVOID = *mut ::std::os::raw::c_void; \ No newline at end of file +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +pub use core_bindings::*; +pub use std::ffi::{OsString}; +pub use std::os::raw::{c_long, c_uint, c_void}; +pub use libc::wchar_t; + +pub const mdTokenNil: mdToken = Helpers_mdTokenNil; +pub const mdModuleNil: mdToken = Helpers_mdModuleNil; +pub const mdTypeRefNil: mdToken = Helpers_mdTypeRefNil; +pub const mdTypeDefNil: mdToken = Helpers_mdTypeDefNil; +pub const mdFieldDefNil: mdToken = Helpers_mdFieldDefNil; +pub const mdMethodDefNil: mdToken = Helpers_mdMethodDefNil; +pub const mdParamDefNil: mdToken = Helpers_mdParamDefNil; +pub const mdInterfaceImplNil: mdToken = Helpers_mdInterfaceImplNil; +pub const mdMemberRefNil: mdToken = Helpers_mdMemberRefNil; +pub const mdCustomAttributeNil: mdToken = Helpers_mdCustomAttributeNil; +pub const mdPermissionNil: mdToken = Helpers_mdPermissionNil; +pub const mdSignatureNil: mdToken = Helpers_mdSignatureNil; +pub const mdEventNil: mdToken = Helpers_mdEventNil; +pub const mdPropertyNil: mdToken = Helpers_mdPropertyNil; +pub const mdModuleRefNil: mdToken = Helpers_mdModuleRefNil; +pub const mdTypeSpecNil: mdToken = Helpers_mdTypeSpecNil; +pub const mdAssemblyNil: mdToken = Helpers_mdAssemblyNil; +pub const mdAssemblyRefNil: mdToken = Helpers_mdAssemblyRefNil; +pub const mdFileNil: mdToken = Helpers_mdFileNil; +pub const mdExportedTypeNil: mdToken = Helpers_mdExportedTypeNil; +pub const mdManifestResourceNil: mdToken = Helpers_mdManifestResourceNil; +pub const mdGenericParamNil: mdToken = Helpers_mdGenericParamNil; +pub const mdGenericParamConstraintNil: mdToken = Helpers_mdGenericParamConstraintNil; +pub const mdMethodSpecNil: mdToken = Helpers_mdMethodSpecNil; +pub const mdStringNil: mdToken = Helpers_mdStringNil; + +pub use super::enums::*; + +pub type CLSID = GUID; + +pub type RO_E_METADATA_NAME_IS_NAMESPACE = Helpers_RO_E_METADATA_NAME_IS_NAMESPACE; + +pub const MAX_IDENTIFIER_LENGTH: usize = 511; + + +pub const COR_CTOR_METHOD_NAME: &'static str = ".ctor"; +pub const COR_CCTOR_METHOD_NAME: &'static str = ".cctor"; +pub const COR_ENUM_FIELD_NAME: &'static str = "value__"; From 0f849a51bb939c336691e04b812b52450486788a Mon Sep 17 00:00:00 2001 From: Osei Fortune Date: Mon, 7 Jun 2021 10:51:51 -0400 Subject: [PATCH 04/11] updates --- core-bindings/build.rs | 5 +- core-bindings/src/bindings.cpp | 105 +++++++-- core-bindings/src/headers.h | 6 + core/src/bindings.rs | 199 ++++++++++++++-- .../metadata/declarations/enum_declaration.rs | 51 +++- .../declarations/struct_declaration.rs | 18 +- .../declarations/struct_field_declaration.rs | 14 +- .../metadata/generic_instance_id_builder.rs | 221 ++++++++++-------- core/src/metadata/meta_data_reader.rs | 57 +++-- 9 files changed, 494 insertions(+), 182 deletions(-) diff --git a/core-bindings/build.rs b/core-bindings/build.rs index fa43418..2ab022e 100644 --- a/core-bindings/build.rs +++ b/core-bindings/build.rs @@ -41,9 +41,10 @@ fn main() { .whitelist_function("IMetaDataImport2_.*") .whitelist_function("Enums_.*") .whitelist_function("Helpers_.*") + .whitelist_function("IRoSimpleMetaDataBuilder_.*") .whitelist_var("Helpers_.*") - .blacklist_type("HSTRING") - .raw_line("pub type HSTRING = *mut windows::HSTRING;") + //.blacklist_type("HSTRING") + //.raw_line("pub type HSTRING = windows::HSTRING;") .clang_args(&["-I", "C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.8\\Include\\um"]) .header("src/bindings.cpp") // Tell cargo to invalidate the built crate whenever any of the diff --git a/core-bindings/src/bindings.cpp b/core-bindings/src/bindings.cpp index 5f61f1d..9fb0e24 100644 --- a/core-bindings/src/bindings.cpp +++ b/core-bindings/src/bindings.cpp @@ -42,24 +42,30 @@ Rometadataresolution_RoParseTypeName(const HSTRING typeName, DWORD *partsCount, return RoParseTypeName(typeName, partsCount, typeNameParts); } + + extern "C" HRESULT Rometadataresolution_RoGetParameterizedTypeInstanceIID(UINT32 nameElementCount, PCWSTR *nameElements, - const IRoMetaDataLocator &metaDataLocator, + HRESULT(*fn)(PCWSTR name, IRoSimpleMetaDataBuilder & builder), GUID *iid, ROPARAMIIDHANDLE *pExtra) { - /*auto proc = (ProcRoGetParameterizedTypeInstanceIID)GetProcAddress( - LoadLibraryA("api-ms-win-ro-typeresolution-l1-1-0.dll"), - "ro_get_parameterized_type_instance_iid"); - return proc(nameElementCount, nameElements, metaDataLocator, iid, pExtra); */ - return RoGetParameterizedTypeInstanceIID(nameElementCount, nameElements, metaDataLocator, iid, pExtra); + + auto locatorImpl{ [&](PCWSTR name, IRoSimpleMetaDataBuilder& builder) { + return fn(name, builder); + } }; + + + //auto const locator = locatorImpl; + + return RoGetParameterizedTypeInstanceIID(nameElementCount, nameElements, Ro::Locator(locatorImpl), iid, pExtra); } -//typedef HRESULT(void* RoLocator)(PCWSTR name, IRoSimpleMetaDataBuilder& builder); +//typedef HRESULT(void* RoLocator)(PCWSTR name, iro_simple_meta_data_builder& builder); -//typedef HRESULT(*RoLocator)(PCWSTR name, IRoSimpleMetaDataBuilder& builder); +//typedef HRESULT(*RoLocator)(PCWSTR name, iro_simple_meta_data_builder& builder); struct _locator { Ro::detail::_Locator locator; @@ -315,6 +321,56 @@ extern "C" HRESULT IMetaDataImport2_GetEventProps(void *meta, mdEvent ev, } +extern "C" HRESULT IMetaDataImport2_FindField(void* meta, mdTypeDef td, + LPCWSTR szName, + PCCOR_SIGNATURE pvSigBlob, + ULONG cbSigBlob, + mdFieldDef * pmb) { + auto metadata = reinterpret_cast(meta); + return metadata->FindField(td, szName, pvSigBlob, cbSigBlob, pmb); +} + + + +extern "C" HRESULT IRoSimpleMetaDataBuilder_SetRuntimeClassSimpleDefault(IRoSimpleMetaDataBuilder* builder, PCWSTR name, + PCWSTR defaultInterfaceName, + const GUID * defaultInterfaceIID) { + return builder->SetRuntimeClassSimpleDefault(name, defaultInterfaceName, defaultInterfaceIID); +} + +extern "C" HRESULT IRoSimpleMetaDataBuilder_SetWinRtInterface(IRoSimpleMetaDataBuilder * builder, GUID iid) { + return builder->SetWinRtInterface(iid); +} + +extern "C" HRESULT IRoSimpleMetaDataBuilder_SetParameterizedInterface(IRoSimpleMetaDataBuilder* builder, GUID piid, + UINT32 numArgs) { + return builder->SetParameterizedInterface(piid,numArgs); +} + +extern "C" HRESULT IRoSimpleMetaDataBuilder_SetEnum(IRoSimpleMetaDataBuilder * builder, PCWSTR name, + PCWSTR baseType) { + return builder->SetEnum(name, baseType); +} + + +extern "C" HRESULT IRoSimpleMetaDataBuilder_SetStruct(IRoSimpleMetaDataBuilder * builder, PCWSTR name, + UINT32 numFields, + const PCWSTR * fieldTypeNames) { + return builder->SetStruct(name, numFields, fieldTypeNames); +} + + +extern "C" HRESULT IRoSimpleMetaDataBuilder_SetDelegate(IRoSimpleMetaDataBuilder * builder, GUID iid) { + return builder->SetDelegate(iid); +} + + +extern "C" HRESULT IRoSimpleMetaDataBuilder_SetParameterizedDelegate(IRoSimpleMetaDataBuilder * builder, GUID piid, + UINT32 numArgs) { + return builder->SetParameterizedDelegate(piid, numArgs); +} + + extern "C" ULONG32 Enums_TypeFromToken(mdToken token) { return TypeFromToken(token); @@ -431,11 +487,28 @@ extern "C" BOOL Helpers_IsEvSpecialName(DWORD value) { return IsEvSpecialName(value); } +extern "C" void Helpers_generate_id_name(PCWSTR* namePartsW, wchar_t* declarationFullName, DWORD * namePartsCount) { + using namespace Microsoft::WRL::Wrappers; + HSTRING* nameParts{ nullptr }; + RoParseTypeName(HStringReference(declarationFullName).Get(), namePartsCount, &nameParts); + + size_t count = (size_t)(namePartsCount); + for (size_t i = 0; i < count; ++i) { + namePartsW[i] = WindowsGetStringRawBuffer(nameParts[i], nullptr); + } + + +} + +extern "C" void Helpers_toString_length(PCWSTR value, size_t * count) { + using namespace Microsoft::WRL::Wrappers; + *count = wcslen(value); +} /* -extern "C" HRESULT GenericInstanceIdBuilder_locatorImpl(PCWSTR name, IRoSimpleMetaDataBuilder & builder) { +extern "C" HRESULT GenericInstanceIdBuilder_locatorImpl(PCWSTR name, iro_simple_meta_data_builder & builder) { shared_ptr declaration{ metadataReader.findByName(name) }; ASSERT(declaration); @@ -445,25 +518,25 @@ extern "C" HRESULT GenericInstanceIdBuilder_locatorImpl(PCWSTR name, IRoSimpleMe ClassDeclaration* classDeclaration{ static_cast(declaration.get()) }; const InterfaceDeclaration& defaultInterface{ classDeclaration->defaultInterface() }; IID defaultInterfaceId = defaultInterface.id(); - ASSERT_SUCCESS(builder.SetRuntimeClassSimpleDefault(name, defaultInterface.fullName().data(), &defaultInterfaceId)); + ASSERT_SUCCESS(builder.set_runtime_class_simple_default(name, defaultInterface.fullName().data(), &defaultInterfaceId)); return S_OK; } case DeclarationKind::Interface: { InterfaceDeclaration* interfaceDeclaration{ static_cast(declaration.get()) }; - ASSERT_SUCCESS(builder.SetWinRtInterface(interfaceDeclaration->id())); + ASSERT_SUCCESS(builder.set_win_rt_interface(interfaceDeclaration->id())); return S_OK; } case DeclarationKind::GenericInterface: { GenericInterfaceDeclaration* genericInterfaceDeclaration{ static_cast(declaration.get()) }; - ASSERT_SUCCESS(builder.SetParameterizedInterface(genericInterfaceDeclaration->id(), genericInterfaceDeclaration->number_of_generic_parameters())); + ASSERT_SUCCESS(builder.set_parameterized_interface(genericInterfaceDeclaration->id(), genericInterfaceDeclaration->number_of_generic_parameters())); return S_OK; } case DeclarationKind::Enum: { EnumDeclaration* enumDeclaration{ static_cast(declaration.get()) }; - ASSERT_SUCCESS(builder.SetEnum(enumDeclaration->fullName().data(), Signature::toString(nullptr, enumDeclaration->type()).data())); + ASSERT_SUCCESS(builder.set_enum(enumDeclaration->fullName().data(), Signature::toString(nullptr, enumDeclaration->type()).data())); return S_OK; } @@ -480,19 +553,19 @@ extern "C" HRESULT GenericInstanceIdBuilder_locatorImpl(PCWSTR name, IRoSimpleMe fieldNamesW.push_back(const_cast(fieldName.data())); } - ASSERT_SUCCESS(builder.SetStruct(structDeclaration->fullName().data(), structDeclaration->size(), fieldNamesW.data())); + ASSERT_SUCCESS(builder.set_struct(structDeclaration->fullName().data(), structDeclaration->size(), fieldNamesW.data())); return S_OK; } case DeclarationKind::Delegate: { DelegateDeclaration* delegateDeclaration{ static_cast(declaration.get()) }; - ASSERT_SUCCESS(builder.SetDelegate(delegateDeclaration->id())); + ASSERT_SUCCESS(builder.set_delegate(delegateDeclaration->id())); return S_OK; } case DeclarationKind::GenericDelegate: { GenericDelegateDeclaration* genericDelegateDeclaration{ static_cast(declaration.get()) }; - ASSERT_SUCCESS(builder.SetParameterizedDelegate(genericDelegateDeclaration->id(), genericDelegateDeclaration->number_of_generic_parameters())); + ASSERT_SUCCESS(builder.set_parameterized_delegate(genericDelegateDeclaration->id(), genericDelegateDeclaration->number_of_generic_parameters())); return S_OK; } diff --git a/core-bindings/src/headers.h b/core-bindings/src/headers.h index 2e7d32a..ac2769c 100644 --- a/core-bindings/src/headers.h +++ b/core-bindings/src/headers.h @@ -9,6 +9,12 @@ #include #include #include + +#include +#include +#include + + const size_t MAX_IDENTIFIER_LENGTH{ 511 }; using identifier = std::array; diff --git a/core/src/bindings.rs b/core/src/bindings.rs index ec826a2..61903e7 100644 --- a/core/src/bindings.rs +++ b/core/src/bindings.rs @@ -9,22 +9,22 @@ pub mod rometadataresolution { ) -> HRESULT { unsafe { windows::HRESULT(core_bindings::Rometadataresolution_RoGetMetaDataFile( - name, meta_data_dispenser.unwrap_or(0 as _), meta_data_file_path.unwrap_or(0 as _), meta_data_import.unwrap_or(0 as _), type_def_token.unwrap_or(0 as _), + std::mem::transmute(name), meta_data_dispenser.unwrap_or(0 as _), meta_data_file_path.unwrap_or(0 as _), meta_data_import.unwrap_or(0 as _), type_def_token.unwrap_or(0 as _), ) as u32) } } pub(crate) fn ro_parse_type_name( - type_name: HSTRING, + mut type_name: HSTRING, parts_count: *mut DWORD, type_name_parts: *mut *mut HSTRING, ) -> HRESULT { unsafe { HRESULT( core_bindings::Rometadataresolution_RoParseTypeName( - type_name, + std::mem::transmute(&mut type_name), parts_count, - type_name_parts, + std::mem::transmute(type_name_parts), ) as u32 ) } @@ -34,7 +34,9 @@ pub mod rometadataresolution { pub(crate) fn ro_get_parameterized_type_instance_iid( name_element_count: UINT32, name_elements: *mut PCWSTR, - meta_data_locator: *const IRoMetaDataLocator, + fn_: ::core::option::Option< + unsafe extern "C" fn(name: PCWSTR, builder: *mut IRoSimpleMetaDataBuilder) -> HRESULT, + >, iid: *mut GUID, p_extra: Option<*mut ROPARAMIIDHANDLE>, ) -> HRESULT { @@ -43,7 +45,7 @@ pub mod rometadataresolution { core_bindings::Rometadataresolution_RoGetParameterizedTypeInstanceIID( name_element_count, name_elements, - meta_data_locator, + fn_ as _, iid, p_extra.unwrap_or(0 as _), ) as u32 @@ -51,15 +53,14 @@ pub mod rometadataresolution { } } - pub(crate) fn ro_locator(fn_: ::core::option::Option< - unsafe extern "C" fn(name: PCWSTR, builder: *mut IRoSimpleMetaDataBuilder) -> HRESULT, - >) -> Ro_detail__Locator< - ::core::option::Option< - unsafe extern "C" fn(arg1: PCWSTR, arg2: *mut IRoSimpleMetaDataBuilder) -> HRESULT, + pub(crate) fn ro_locator( + fn_: ::core::option::Option< + unsafe extern "C" fn(name: PCWSTR, builder: *mut IRoSimpleMetaDataBuilder) -> i32, >, - > { + locator: *mut Locator, + ) { unsafe { - core_bindings::Rometadataresolution_Ro_Locator(fn_) + core_bindings::Rometadataresolution_Ro_Locator(fn_, locator) } } } @@ -488,6 +489,152 @@ pub mod imeta_data_import2 { ) } } + + + pub(crate) fn find_field( + meta: *mut c_void, + td: mdTypeDef, + sz_name: Option, + pv_sig_blob: Option, + cb_sig_blob: Option, + pmb: Option<*mut mdFieldDef>, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_FindField( + meta, + td, + sz_name.unwrap_or(0 as _), + pv_sig_blob.unwrap_or(0 as _), + cb_sig_blob.unwrap_or_default(), + pmb.unwrap_or(0 as _), + ) as u32 + ) + } + } +} + +pub mod iro_simple_meta_data_builder { + use crate::prelude::*; + use windows::{HRESULT, HSTRING}; + + pub(crate) fn set_runtime_class_simple_default( + builder: *mut IRoSimpleMetaDataBuilder, + name: PCWSTR, + default_interface_name: PCWSTR, + default_interface_iid: *const GUID, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IRoSimpleMetaDataBuilder_SetRuntimeClassSimpleDefault( + builder, + name, + default_interface_name, + default_interface_iid, + ) as u32 + ) + } + } + + + pub(crate) fn set_win_rt_interface( + builder: *mut IRoSimpleMetaDataBuilder, + iid: GUID, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IRoSimpleMetaDataBuilder_SetWinRtInterface( + builder, + iid, + ) as u32 + ) + } + } + + + pub fn set_parameterized_interface( + builder: *mut IRoSimpleMetaDataBuilder, + piid: GUID, + num_args: UINT32, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IRoSimpleMetaDataBuilder_SetParameterizedInterface( + builder, + piid, + num_args, + ) as u32 + ) + } + } + + + pub fn set_enum( + builder: *mut IRoSimpleMetaDataBuilder, + name: PCWSTR, + base_type: PCWSTR, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IRoSimpleMetaDataBuilder_SetEnum( + builder, + name, + base_type, + ) as u32 + ) + } + } + + + pub fn set_struct( + builder: *mut IRoSimpleMetaDataBuilder, + name: PCWSTR, + num_fields: UINT32, + field_type_names: *const PCWSTR, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IRoSimpleMetaDataBuilder_SetStruct( + builder, + name, + num_fields, + field_type_names, + ) as u32 + ) + } + } + + + pub fn set_delegate( + builder: *mut IRoSimpleMetaDataBuilder, + iid: GUID, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IRoSimpleMetaDataBuilder_SetDelegate( + builder, + iid, + ) as u32 + ) + } + } + + + pub fn set_parameterized_delegate( + builder: *mut IRoSimpleMetaDataBuilder, + piid: GUID, + num_args: UINT32, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IRoSimpleMetaDataBuilder_SetParameterizedDelegate( + builder, + piid, + num_args, + ) as u32 + ) + } + } } pub mod enums { @@ -588,9 +735,9 @@ pub mod helpers { } } - pub(crate) fn windows_get_string_raw_buffer(string: HSTRING, length: Option<*mut UINT32>) -> PCWSTR { + pub(crate) fn windows_get_string_raw_buffer(mut string: HSTRING, length: Option<*mut UINT32>) -> PCWSTR { unsafe { - core_bindings::Helpers_WindowsGetStringRawBuffer(string: HSTRING, length.unwrap_or(0 as _)) + core_bindings::Helpers_WindowsGetStringRawBuffer(std::mem::transmute(&mut string), length.unwrap_or(0 as _)) } } @@ -611,6 +758,28 @@ pub mod helpers { core_bindings::Helpers_IsEvSpecialName(value) == 1 } } + + pub(crate) fn generate_id_name( + name_parts_w: *mut PCWSTR, + declaration_full_name: *mut u16, + name_parts_count: *mut DWORD, + ) { + unsafe { + core_bindings::Helpers_generate_id_name( + name_parts_w, + declaration_full_name, + name_parts_count, + ) + } + } + + pub(crate) fn to_string_length(value: PCWSTR, count: *mut usize) { + unsafe { + core_bindings::Helpers_toString_length(value: PCWSTR, count: *mut usize); + } + } + + } diff --git a/core/src/metadata/declarations/enum_declaration.rs b/core/src/metadata/declarations/enum_declaration.rs index 812c30b..29640d2 100644 --- a/core/src/metadata/declarations/enum_declaration.rs +++ b/core/src/metadata/declarations/enum_declaration.rs @@ -1,5 +1,7 @@ use crate::prelude::*; - +use crate::bindings::{ + imeta_data_import2, helpers +}; use super::{ declaration::{ Declaration, @@ -7,34 +9,65 @@ use super::{ }, type_declaration::TypeDeclaration, }; +use std::borrow::Cow; #[derive(Debug)] pub struct EnumDeclaration<'a> { - type_declaration: TypeDeclaration<'a>, + base: TypeDeclaration<'a>, } impl Declaration for EnumDeclaration { fn is_exported(&self) -> bool { - self.type_declaration.is_exported() + self.base.is_exported() } - fn name<'a>(&self) -> &'a str { - self.type_declaration.name() + fn name<'a>(&self) -> Cow<'a, str> { + self.base.name() } - fn full_name<'a>(&self) -> &'a str { - self.type_declaration.full_name() + fn full_name<'a>(&self) -> Cow<'a, str> { + self.base.full_name() } fn kind(&self) -> DeclarationKind { - self.type_declaration.kind + self.base.kind } } impl EnumDeclaration { pub fn new(metadata: *mut c_void, token: mdTypeDef) -> Self { Self { - type_declaration: TypeDeclaration::new(DeclarationKind::Enum, metadata, token) + base: TypeDeclaration::new(DeclarationKind::Enum, metadata, token) } } + + pub fn type_<'a>(&self) -> Cow<'a, &[u8]>{ + let mut type_field = mdTokenNil; + let name_w = OsString::from(COR_ENUM_FIELD_NAME).to_wide(); + debug_assert!(imeta_data_import2::find_field( + self.base.metadata, self.base.token, + Some(name_w.as_ptr()), None, None, Some(&mut type_field) + ).is_ok()); + let mut signature = [0_u8;MAX_IDENTIFIER_LENGTH]; + let mut signature_size = 0; + debug_assert!( + imeta_data_import2::get_field_props( + self.base.metadata, + type_field, + None, None, None, None, None, + Some(&mut signature.as_mut_ptr() as _ as *mut *const u8), + Some(&mut signature_size), + None, None, None + ).is_ok() + ); + + let header= helpers::cor_sig_uncompress_data(signature.as_ptr()); + debug_assert!( + header == CorCallingConvention::ImageCeeCsCallconvField as u32 + ); + + let result:&[u8] = &signature[0..signature_size]; + + result.into() + } } \ No newline at end of file diff --git a/core/src/metadata/declarations/struct_declaration.rs b/core/src/metadata/declarations/struct_declaration.rs index 4aa2b8b..b9284bf 100644 --- a/core/src/metadata/declarations/struct_declaration.rs +++ b/core/src/metadata/declarations/struct_declaration.rs @@ -3,6 +3,7 @@ use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; use crate::metadata::declarations::type_declaration::TypeDeclaration; use crate::bindings::imeta_data_import2; use crate::metadata::declarations::struct_field_declaration::StructFieldDeclaration; +use std::borrow::Cow; pub struct StructDeclaration<'a> { base: TypeDeclaration<'a>, @@ -10,11 +11,11 @@ pub struct StructDeclaration<'a> { } impl Declaration for StructDeclaration { - fn name<'a>(&self) -> &'a str { + fn name<'a>(&self) -> Cow<'a, str> { self.base.name() } - fn full_name<'a>(&self) -> &'a str { + fn full_name<'a>(&self) -> Cow<'a, str> { self.base.full_name() } @@ -38,17 +39,22 @@ impl StructDeclaration { self.fields.len() } + pub fn fields(&self) -> &[StructFieldDeclaration] { + self.fields.as_slice() + } + fn make_field_declarations(metadata: *mut c_void, token: mdTypeDef) -> Vec { - let enumerator = std::ptr::null_mut(); + let mut enumerator = std::ptr::null_mut(); let mut count = 0; - let mut tokens: Vec = vec![0; 1024]; + let mut tokens = [0; 1024]; + let mut enumerator_ptr = &mut enumerator; debug_assert!( imeta_data_import2::enum_fields( - metadata, enumerator, token, tokens.as_mut_ptr(), tokens.len(), &mut count, + metadata, enumerator_ptr, token, tokens.as_mut_ptr(), tokens.len() as u32, &mut count, ).is_ok() ); - debug_assert!(count < tokens.len() - 1); + debug_assert!(count < (tokens.len() - 1) as u32); imeta_data_import2::close_enum(metadata, enumerator); diff --git a/core/src/metadata/declarations/struct_field_declaration.rs b/core/src/metadata/declarations/struct_field_declaration.rs index 5d048b5..91e703e 100644 --- a/core/src/metadata/declarations/struct_field_declaration.rs +++ b/core/src/metadata/declarations/struct_field_declaration.rs @@ -2,6 +2,7 @@ use crate::prelude::*; use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; use crate::metadata::declarations::field_declaration::FieldDeclaration; use crate::bindings::{imeta_data_import2, helpers}; +use std::borrow::Cow; pub struct StructFieldDeclaration<'a> { base: FieldDeclaration<'a>, @@ -32,23 +33,24 @@ impl StructFieldDeclaration { } } - pub fn type_(&self) -> PCCOR_SIGNATURE { - let mut signature = vec![0_u8; MAX_IDENTIFIER_LENGTH]; + pub fn type_<'a>(&self) -> Cow<'a, [u8]> { + let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; let mut signature_size = 0; debug_assert!( imeta_data_import2::get_field_props( self.base.metadata, self.base.token, None, None, None, - None, None, Some(signature.as_mut_ptr()), Some(&mut signature_size), + None, None, Some(signature.as_mut_ptr() as *mut *const u8), Some(&mut signature_size), None, None, None, ).is_ok() ); - signature.resize(signature_size, 0); + let header = helpers::cor_sig_uncompress_data(signature.as_mut_ptr()); debug_assert!( - header == CorCallingConvention::ImageCeeCsCallconvField + header == CorCallingConvention::ImageCeeCsCallconvField as u32 ); - return signature; + let result: [u8] = signature[..signature_size]; + result.into() } } \ No newline at end of file diff --git a/core/src/metadata/generic_instance_id_builder.rs b/core/src/metadata/generic_instance_id_builder.rs index 06d8919..795aa8c 100644 --- a/core/src/metadata/generic_instance_id_builder.rs +++ b/core/src/metadata/generic_instance_id_builder.rs @@ -4,153 +4,168 @@ use crate::bindings::helpers; use crate::metadata::meta_data_reader::MetadataReader; pub struct GenericInstanceIdBuilder {} -pub use crate::bindings::rometadataresolution; +pub use crate::bindings::{rometadataresolution, iro_simple_meta_data_builder}; use core_bindings::GUID; use crate::metadata::declarations::class_declaration::ClassDeclaration; use std::sync::Arc; - +use windows::HRESULT; +use crate::metadata::declarations::interface_declaration::{InterfaceDeclaration, GenericInterfaceDeclaration}; +use crate::metadata::declarations::enum_declaration::EnumDeclaration; +use crate::metadata::signature::Signature; +use crate::metadata::declarations::struct_declaration::StructDeclaration; +use crate::metadata::declarations::delegate_declaration::{DelegateDeclaration, GenericDelegateDeclaration}; impl GenericInstanceIdBuilder { extern "C" fn locator_impl(name: PCWSTR, builder: *mut IRoSimpleMetaDataBuilder) -> windows::HRESULT { - let declaration = MetadataReader::find_by_name(name); + let declaration = MetadataReader::find_by_name_w(name); debug_assert!(declaration.is_some()); if let Some(declaration) = declaration { match declaration.kind() { DeclarationKind::Class => { - let mut classDeclaration = declaration + let mut class_declaration = declaration .as_any() .downcast_ref::() .unwrap(); - let defaultInterface = classDeclaration.default_interface(); - let defaultInterfaceId = defaultInterface.id(); + let default_interface = class_declaration.default_interface(); + let default_interface_id = default_interface.id(); + let full_name = OsString::from(default_interface.full_name()); + let full_name_w = full_name.to_wide(); debug_assert!( - + iro_simple_meta_data_builder::set_runtime_class_simple_default( + builder, name, full_name_w.as_ptr(), + &default_interface_id + ) ); - ASSERT_SUCCESS(builder.SetRuntimeClassSimpleDefault(name, defaultInterface.fullName().data(), &defaultInterfaceId)); - return S_OK; + return HRESULT::from_win32(0) } - DeclarationKind::Interface => {} - DeclarationKind::GenericInterface => {} - DeclarationKind::GenericInterfaceInstance => {} - DeclarationKind::Enum => {} - DeclarationKind::EnumMember => {} - DeclarationKind::Struct => {} - DeclarationKind::StructField => {} - DeclarationKind::Delegate => {} - DeclarationKind::GenericDelegate => {} - DeclarationKind::GenericDelegateInstance => {} - DeclarationKind::Event => {} - DeclarationKind::Property => {} - DeclarationKind::Method => {} - DeclarationKind::Parameter => {} - } - } - DeclarationKind kind{ declaration->kind() }; - switch (kind) { - case DeclarationKind::Class: { - ClassDeclaration* classDeclaration{ static_cast(declaration.get()) }; - const InterfaceDeclaration& defaultInterface{ classDeclaration->defaultInterface() }; - IID defaultInterfaceId = defaultInterface.id(); - ASSERT_SUCCESS(builder.SetRuntimeClassSimpleDefault(name, defaultInterface.fullName().data(), &defaultInterfaceId)); - return S_OK; - } - - case DeclarationKind::Interface: { - InterfaceDeclaration* interfaceDeclaration{ static_cast(declaration.get()) }; - ASSERT_SUCCESS(builder.SetWinRtInterface(interfaceDeclaration->id())); - return S_OK; - } + DeclarationKind::Interface => { + let mut interface_declaration = declaration + .as_any() + .downcast_ref::() + .unwrap(); + let interface_declaration_id = interface_declaration.id(); + iro_simple_meta_data_builder::set_win_rt_interface( + builder,interface_declaration_id + ); + HRESULT::from_win32(0) + } + DeclarationKind::GenericInterface => { + let mut generic_interface_declaration = declaration + .as_any() + .downcast_ref::() + .unwrap(); + debug_assert!( + iro_simple_meta_data_builder::set_parameterized_interface( + builder, generic_interface_declaration.id(), generic_interface_declaration.number_of_generic_parameters() as u32 + ).is_ok() + ); + HRESULT::from_win32(0) + } + DeclarationKind::Enum => { + let mut enum_declaration = declaration + .as_any() + .downcast_ref::() + .unwrap(); + let type_ = enum_declaration.type_().into_owned(); + let full_name_w = enum_declaration.full_name().to_owned().to_wide(); + let signature = Signature::to_string( + std::ptr::null() as _, type_.as_ptr() + ); + let signature_w = signature.to_wide(); + debug_assert!( + iro_simple_meta_data_builder::set_enum( + builder, full_name_w.as_ptr(), + signature_w.as_ptr() + ).is_ok() + ); + HRESULT::from_win32(0) + } + DeclarationKind::Struct => { - case DeclarationKind::GenericInterface: { - GenericInterfaceDeclaration* genericInterfaceDeclaration{ static_cast(declaration.get()) }; - ASSERT_SUCCESS(builder.SetParameterizedInterface(genericInterfaceDeclaration->id(), genericInterfaceDeclaration->numberOfGenericParameters())); - return S_OK; - } + let mut struct_declaration = declaration + .as_any() + .downcast_ref::() + .unwrap(); - case DeclarationKind::Enum: { - EnumDeclaration* enumDeclaration{ static_cast(declaration.get()) }; - ASSERT_SUCCESS(builder.SetEnum(enumDeclaration->fullName().data(), Signature::toString(nullptr, enumDeclaration->type()).data())); - return S_OK; - } + let mut field_names = Vec::new(); + for field in struct_declaration.fields().iter() { + field_names.push( + Signature::to_string( + field.base.metadata, field.type_() + ).to_wide().as_ptr() + ) + } - case DeclarationKind::Struct: { - StructDeclaration* structDeclaration{ static_cast(declaration.get()) }; + let full_name = struct_declaration.full_name().into_owned().to_wide(); + debug_assert!( + iro_simple_meta_data_builder::set_struct( + builder, full_name.as_ptr(), + struct_declaration.size() as u32, + field_names.as_ptr() + ).is_ok() + ); - vector fieldNames; - for (const StructFieldDeclaration& field : *structDeclaration) { - fieldNames.push_back(Signature::toString(field._metadata.Get(), field.type())); + HRESULT::from_win32(0) } + DeclarationKind::Delegate => { + let mut delegate_declaration = declaration + .as_any() + .downcast_ref::() + .unwrap(); - vector fieldNamesW; - for (wstring& fieldName : fieldNames) { - fieldNamesW.push_back(const_cast(fieldName.data())); + debug_assert!( + iro_simple_meta_data_builder::set_delegate( + builder, delegate_declaration.id() + ).is_ok() + ); + HRESULT::from_win32(0) + } + DeclarationKind::GenericDelegate => { + let mut generic_delegate_declaration = declaration + .as_any() + .downcast_ref::() + .unwrap(); + debug_assert!( + iro_simple_meta_data_builder::set_parameterized_delegate( + builder, generic_delegate_declaration.id(), generic_delegate_declaration.number_of_generic_parameters() as u32 + ) + ) + } + _ => { + std::unreachable!() } - - ASSERT_SUCCESS(builder.SetStruct(structDeclaration->fullName().data(), structDeclaration->size(), fieldNamesW.data())); - return S_OK; - } - - case DeclarationKind::Delegate: { - DelegateDeclaration* delegateDeclaration{ static_cast(declaration.get()) }; - ASSERT_SUCCESS(builder.SetDelegate(delegateDeclaration->id())); - return S_OK; - } - - case DeclarationKind::GenericDelegate: { - GenericDelegateDeclaration* genericDelegateDeclaration{ static_cast(declaration.get()) }; - ASSERT_SUCCESS(builder.SetParameterizedDelegate(genericDelegateDeclaration->id(), genericDelegateDeclaration->numberOfGenericParameters())); - return S_OK; } - - default: - ASSERT_NOT_REACHED(); } + std::unreachable!() } pub fn generate_id(declaration: &dyn Declaration){ - let declaration_full_name = declaration.full_name(); - let mut name_ref = windows::HSTRING::from(declaration_full_name); - let cap = vec![0_u16;MAX_IDENTIFIER_LENGTH]; - let mut nameParts = windows::HSTRING::from_wide(cap.as_slice()); - let mut name_parts_ref = &mut nameParts.as_mut_ptr(); - let mut namePartsCount = 0; - debug_assert!( - rometadataresolution::ro_parse_type_name( - name_ref, &mut namePartsCount, name_parts_ref - ).is_ok() - ); - - let mut namePartsW = vec![0_u16; 128]; - debug_assert!( - namePartsCount < namePartsW.len() as u32 - ); - - for i in 0..namePartsCount { - namePartsCount[i] = helpers::windows_get_string_raw_buffer(nameParts.as_wide()[i],None) - } + let mut declaration_full_name = declaration.full_name().into_owned().to_wide(); + let mut name_parts = [0_u16;MAX_IDENTIFIER_LENGTH]; + let mut name_parts_count = 0; + let mut name_parts_w = &mut name_parts.as_ptr(); + helpers::generate_id_name(name_parts_w, declaration_full_name.as_mut_ptr(), &mut name_parts_count); let mut guid = GUID::default(); debug_assert!( rometadataresolution::ro_get_parameterized_type_instance_iid( - namePartsCount, namePartsW.as_mut_ptr(), rometadataresolution::ro_locator( - Option(GenericInstanceIdBuilder::locator_impl) - ), &mut guid, None + name_parts_count, namePartsW.as_mut_ptr(), Option(GenericInstanceIdBuilder::locator_impl), &mut guid, None ) ); /* - for (size_t i = 0; i < namePartsCount; ++i) { - ASSERT_SUCCESS(WindowsDeleteString(nameParts[i])); + for (size_t i = 0; i < name_parts_count; ++i) { + ASSERT_SUCCESS(WindowsDeleteString(name_parts[i])); } */ - //CoTaskMemFree(nameParts); + //CoTaskMemFree(name_parts); return guid; } - // HRESULT locatorImpl(PCWSTR name, IRoSimpleMetaDataBuilder& builder); + // HRESULT locatorImpl(PCWSTR name, iro_simple_meta_data_builder& builder); } \ No newline at end of file diff --git a/core/src/metadata/meta_data_reader.rs b/core/src/metadata/meta_data_reader.rs index 9273380..f0dd4a1 100644 --- a/core/src/metadata/meta_data_reader.rs +++ b/core/src/metadata/meta_data_reader.rs @@ -10,6 +10,7 @@ use windows::HSTRING; use crate::metadata::declarations::declaration::DeclarationKind::GenericInterfaceInstance; use crate::metadata::declarations::struct_declaration::StructDeclaration; use crate::metadata::declarations::class_declaration::ClassDeclaration; +use std::ffi::OsStr; const WINDOWS: &'static src = "Windows"; const SYSTEM_ENUM: &'static src = "System.Enum"; @@ -19,59 +20,65 @@ const SYSTEM_MULTICASTDELEGATE: &'static src = "System.MulticastDelegate"; pub struct MetadataReader {} impl MetadataReader { - pub fn find_by_name(full_name:&str) -> Option>{ + pub fn find_by_name_w(full_name: PCWSTR) -> Option> { + let mut count = 0; + helpers::to_string_length(full_name, &mut count); + let slice = unsafe { std::slice::from_raw_parts(full_name, count) }; + let name = OsString::from_wide(slice).to_string_lossy(); + MetadataReader::find_by_name(name.as_ref()) + } + pub fn find_by_name(full_name: &str) -> Option> { if full_name.is_empty() { return Some( Arc::new( NamespaceDeclaration::new("") ) - ) + ); } let mut metadata = std::ptr::null_mut(); let meta = &mut metadata; let mut token = mdTokenNil; let mut full_name_hstring = HSTRING::from(full_name); let get_metadata_file_result = rometadataresolution::ro_get_meta_data_file( - &mut full_name_hstring, None, None, Some(meta), Some(&mut token) + &mut full_name_hstring, None, None, Some(meta), Some(&mut token), ); if get_metadata_file_result.is_err() { if get_metadata_file_result == RO_E_METADATA_NAME_IS_NAMESPACE { return Some( Arc::new(NamespaceDeclaration::new(full_name)) - ) + ); } - return None + return None; } let mut flags = 0; let mut parent_token = mdTokenNil; debug_assert!(imeta_data_import2::get_type_def_props( - metadata, token, None, None, None, Some(&mut flags), Some(&mut parent_token) + metadata, token, None, None, None, Some(&mut flags), Some(&mut parent_token), ).is_ok()); - if helpers::is_td_class(flags) { let mut parent_name = vec![0_u16; MAX_IDENTIFIER_LENGTH]; match enums::type_from_token(parent_token) { - mdtTypeDef => { - debug_assert!( - imeta_data_import2::get_type_def_props( - metadata,parent_token, Some(parent_name.as_mut_ptr()), Some(parent_name.len()), - None, None, None - ).is_ok() - ); - } + mdtTypeDef => { + debug_assert!( + imeta_data_import2::get_type_def_props( + metadata, parent_token, Some(parent_name.as_mut_ptr()), Some(parent_name.len() as u32), + None, None, None, + ).is_ok() + ); + } mdtTypeRef => { debug_assert!( imeta_data_import2::get_type_ref_props( - metadata, parent_name, None, Some(parent_name.as_mut_ptr()), Some(parent_name.len()), None + metadata, parent_name, None, Some(parent_name.as_mut_ptr()), Some(parent_name.len()), None, ).is_ok() ) } - _=> { + _ => { std::unreachable!() } } @@ -83,7 +90,7 @@ impl MetadataReader { Arc::new( EnumDeclaration::new(metadata, token) ) - ) + ); } if parent_name_string == SYSTEM_VALUETYPE { @@ -91,22 +98,22 @@ impl MetadataReader { Arc::new( StructDeclaration::new(metadata, token) ) - ) + ); } if parent_name_string == SYSTEM_MULTICASTDELEGATE { - if full_name.contains("`"){ + if full_name.contains("`") { return Some( Arc::new( GenericDelegateDeclaration::new(metadata, token) ) - ) - }else { + ); + } else { return Some( Arc::new( DelegateDeclaration::new(metadata, token) ) - ) + ); } } @@ -114,7 +121,7 @@ impl MetadataReader { Arc::new( ClassDeclaration::new(metadata, token) ) - ) + ); } if helpers::is_td_interface(flags) { @@ -130,7 +137,7 @@ impl MetadataReader { InterfaceDeclaration::new(metadata, token) ) ) - } + }; } std::unreachable!(); From eab5c3cbc6eb38d5cfb4488ffa36a8fbc47a49a0 Mon Sep 17 00:00:00 2001 From: Osei Fortune Date: Mon, 7 Jun 2021 11:49:22 -0400 Subject: [PATCH 05/11] updates --- core/src/metadata/com_helpers.rs | 25 +++++++++++++ .../declarations/class_declaration.rs | 35 +++++++++++-------- .../metadata/generic_instance_id_builder.rs | 11 +----- core/src/metadata/meta_data_reader.rs | 21 +++++------ 4 files changed, 58 insertions(+), 34 deletions(-) diff --git a/core/src/metadata/com_helpers.rs b/core/src/metadata/com_helpers.rs index a0eec36..debb2cc 100755 --- a/core/src/metadata/com_helpers.rs +++ b/core/src/metadata/com_helpers.rs @@ -1,5 +1,6 @@ use crate::prelude::*; use crate::bindings::{helpers, imeta_data_import2, enums, rometadataresolution}; +use std::borrow::Cow; const GUID_ATTRIBUTE: &'static str = "Windows.Foundation.Metadata.GuidAttribute"; @@ -82,3 +83,27 @@ pub fn get_guid_attribute_value(metadata: *mut c_void, token: mdToken) -> GUID { ); guid } + +pub fn getTypeName(metadata: *mut c_void, token: mdToken) -> &str { +debug_assert!(!metadata.is_null()); +ASSERT(token != mdTokenNil); + +identifier nameData; +ULONG nameLength{ 0 }; + +switch (TypeFromToken(token)) { +case mdtTypeDef: +ASSERT_SUCCESS(metadata->GetTypeDefProps(token, nameData.data(), nameData.size(), &nameLength, nullptr, nullptr)); +break; + +case mdtTypeRef: +ASSERT_SUCCESS(metadata->GetTypeRefProps(token, nullptr, nameData.data(), nameData.size(), &nameLength)); +break; + +default: +ASSERT_NOT_REACHED(); +} + +wstring result{ nameData.data(), nameLength - 1 }; +return result; +} \ No newline at end of file diff --git a/core/src/metadata/declarations/class_declaration.rs b/core/src/metadata/declarations/class_declaration.rs index a9b8fb0..f12c94d 100644 --- a/core/src/metadata/declarations/class_declaration.rs +++ b/core/src/metadata/declarations/class_declaration.rs @@ -8,8 +8,9 @@ use crate::bindings::{helpers, imeta_data_import2}; use std::str::FromStr; use crate::metadata::declaration_factory::DeclarationFactory; use std::sync::Arc; -use crate::metadata::declarations::base_class_declaration::BaseClassDeclaration; +use crate::metadata::declarations::base_class_declaration::{BaseClassDeclaration, BaseClassDeclarationImpl}; use crate::metadata::declarations::declaration::DeclarationKind; +use crate::bindings::helpers::get_type_name; const DEFAULT_ATTRIBUTE:&'static str = "Windows.Foundation.Metadata.DefaultAttribute"; @@ -23,7 +24,8 @@ pub struct ClassDeclaration<'a> { impl ClassDeclaration { fn make_initializer_declarations(metadata: *mut c_void, token: mdTypeDef) -> Vec{ - let enumerator = std::ptr::null_mut(); + let mut enumerator = std::ptr::null_mut(); + let enumerator_ptr = &mut enumerator; let mut count = 0; let mut tokens:Vec = vec![0;1024]; @@ -31,12 +33,12 @@ impl ClassDeclaration { let name = name.to_wide(); debug_assert!( imeta_data_import2::enum_methods_with_name( - metadata, enumerator, token, name.as_ptr(), tokens.as_mut_ptr(), - tokens.len(), &mut count + metadata, enumerator_ptr, token, name.as_ptr(), tokens.as_mut_ptr(), + tokens.len() as u32, &mut count ).is_ok() ); - debug_assert!(count < tokens.len() - 1); + debug_assert!(count < (tokens.len() - 1) as u32); imeta_data_import2::close_enum(metadata, enumerator); @@ -69,18 +71,19 @@ impl ClassDeclaration { fn make_default_interface(metadata: *mut c_void, token: mdTypeDef) -> Option> { let mut interface_impl_tokens = vec![0_1024]; let mut interface_impl_count = 0; - let interface_enumerator = std::ptr::null_mut(); + let mut interface_enumerator = std::ptr::null_mut(); + let interface_enumerator_ptr = &mut interface_enumerator; debug_assert!( imeta_data_import2::enum_interface_impls( - metadata, interface_enumerator, token, - Some(interface_impl_tokens.as_mut_ptr()), Some(interface_impl_tokens.len()), + metadata, interface_enumerator_ptr, Some(token), + Some(interface_impl_tokens.as_mut_ptr()), Some(interface_impl_tokens.len() as u32), Some(&mut interface_impl_count) ).is_ok() ); debug_assert!(interface_impl_count < interface_impl_tokens.size()); imeta_data_import2::close_enum(metadata, interface_enumerator); - let attr = OsString::from_str(DEFAULT_ATTRIBUTE).unwrap().to_wide(); + let attr = DEFAULT_ATTRIBUTE.to_wide(); for i in 0..interface_impl_count { let interface_impl_token = interface_impl_tokens[i]; let get_custom_attribute_result = imeta_data_import2::get_custom_attribute_by_name( @@ -116,15 +119,19 @@ impl ClassDeclaration { } pub fn base_full_name(&self) -> &str { - let mut parentToken = mdTokenNil; + let mut parent_token = mdTokenNil; + let base = self.base.base(); debug_assert!( imeta_data_import2::get_type_def_props( - self.base + base.metadata, + base.token, + None, None,None,None, + Some(&mut parent_token) ) ); - ASSERT_SUCCESS(_metadata->GetTypeDefProps(_token, nullptr, 0, nullptr, nullptr, &parentToken)); - - return getTypeName(_metadata.Get(), parentToken); + let mut name = [0_u16; MAX_IDENTIFIER_LENGTH]; + get_type_name(base.metadata, parent_token, name.as_mut_ptr(), count); + return getTypeName(_metadata.Get(), parent_token); } pub fn default_interface(&self) -> &InterfaceDeclaration{ diff --git a/core/src/metadata/generic_instance_id_builder.rs b/core/src/metadata/generic_instance_id_builder.rs index 795aa8c..05faf0c 100644 --- a/core/src/metadata/generic_instance_id_builder.rs +++ b/core/src/metadata/generic_instance_id_builder.rs @@ -141,7 +141,7 @@ impl GenericInstanceIdBuilder { std::unreachable!() } - pub fn generate_id(declaration: &dyn Declaration){ + pub fn generate_id(declaration: &dyn Declaration) -> GUID { let mut declaration_full_name = declaration.full_name().into_owned().to_wide(); let mut name_parts = [0_u16;MAX_IDENTIFIER_LENGTH]; let mut name_parts_count = 0; @@ -156,16 +156,7 @@ impl GenericInstanceIdBuilder { ) ); - /* - for (size_t i = 0; i < name_parts_count; ++i) { - ASSERT_SUCCESS(WindowsDeleteString(name_parts[i])); - } - */ - - //CoTaskMemFree(name_parts); - return guid; } - // HRESULT locatorImpl(PCWSTR name, iro_simple_meta_data_builder& builder); } \ No newline at end of file diff --git a/core/src/metadata/meta_data_reader.rs b/core/src/metadata/meta_data_reader.rs index f0dd4a1..8c764ba 100644 --- a/core/src/metadata/meta_data_reader.rs +++ b/core/src/metadata/meta_data_reader.rs @@ -3,7 +3,6 @@ use std::sync::Arc; use crate::metadata::declarations::declaration::Declaration; use crate::metadata::declarations::namespace_declaration::NamespaceDeclaration; use crate::metadata::declarations::enum_declaration::EnumDeclaration; -use crate::metadata::declarations::d use crate::metadata::declarations::delegate_declaration::{GenericDelegateDeclaration, InterfaceDeclaration, DelegateDeclaration}; use crate::bindings::{rometadataresolution, imeta_data_import2, helpers, enums}; use windows::HSTRING; @@ -11,6 +10,7 @@ use crate::metadata::declarations::declaration::DeclarationKind::GenericInterfac use crate::metadata::declarations::struct_declaration::StructDeclaration; use crate::metadata::declarations::class_declaration::ClassDeclaration; use std::ffi::OsStr; +use crate::metadata::declarations::interface_declaration::{GenericInterfaceDeclaration, InterfaceDeclaration}; const WINDOWS: &'static src = "Windows"; const SYSTEM_ENUM: &'static src = "System.Enum"; @@ -62,8 +62,9 @@ impl MetadataReader { if helpers::is_td_class(flags) { let mut parent_name = vec![0_u16; MAX_IDENTIFIER_LENGTH]; - match enums::type_from_token(parent_token) { - mdtTypeDef => { + + match CorTokenType::from(enums::type_from_token(parent_token)) { + CorTokenType::mdtTypeDef => { debug_assert!( imeta_data_import2::get_type_def_props( metadata, parent_token, Some(parent_name.as_mut_ptr()), Some(parent_name.len() as u32), @@ -71,10 +72,10 @@ impl MetadataReader { ).is_ok() ); } - mdtTypeRef => { + CorTokenType::mdtTypeRef => { debug_assert!( imeta_data_import2::get_type_ref_props( - metadata, parent_name, None, Some(parent_name.as_mut_ptr()), Some(parent_name.len()), None, + metadata, parent_token, None, Some(parent_name.as_mut_ptr()), Some(parent_name.len() as u32), None, ).is_ok() ) } @@ -102,18 +103,18 @@ impl MetadataReader { } if parent_name_string == SYSTEM_MULTICASTDELEGATE { - if full_name.contains("`") { - return Some( + return if full_name.contains("`") { + Some( Arc::new( GenericDelegateDeclaration::new(metadata, token) ) - ); + ) } else { - return Some( + Some( Arc::new( DelegateDeclaration::new(metadata, token) ) - ); + ) } } From 753f9c607fd787a8b5f0eadd1632539fe472d9d8 Mon Sep 17 00:00:00 2001 From: Osei Fortune Date: Tue, 8 Jun 2021 11:39:38 -0400 Subject: [PATCH 06/11] updates --- core-bindings/build.rs | 1 + core-bindings/src/bindings.cpp | 18 ++ core/src/bindings.rs | 65 ++++-- core/src/enums.rs | 5 +- core/src/lib.rs | 2 +- core/src/metadata/com_helpers.rs | 53 ++--- core/src/metadata/declaration_factory.rs | 196 ++++++++++------ .../declarations/base_class_declaration.rs | 184 ++++++++------- .../declarations/class_declaration.rs | 73 +++--- .../generic_delegate_declaration.rs | 66 ++++++ .../generic_delegate_instance_declaration.rs | 74 ++++++ .../declarations/delegate_declaration/mod.rs | 148 +++--------- .../metadata/declarations/enum_declaration.rs | 104 ++++----- .../declarations/event_declaration.rs | 25 +-- .../declarations/field_declaration.rs | 103 ++++----- .../declarations/interface_declaration.rs | 212 ------------------ .../generic_interface_declaration.rs | 83 +++++++ .../generic_interface_instance_declaration.rs | 90 ++++++++ .../declarations/interface_declaration/mod.rs | 80 +++++++ .../declarations/method_declaration.rs | 40 ++-- .../declarations/namespace_declaration.rs | 87 ++++++- .../declarations/parameter_declaration.rs | 38 ++-- .../declarations/property_declaration.rs | 22 +- .../declarations/struct_declaration.rs | 11 +- .../declarations/struct_field_declaration.rs | 19 +- .../metadata/declarations/type_declaration.rs | 14 +- .../metadata/generic_instance_id_builder.rs | 86 ++++--- core/src/metadata/meta_data_reader.rs | 31 +-- core/src/metadata/signature.rs | 94 ++++---- core/src/prelude.rs | 3 +- core/src/runtime/com/mod.rs | 0 core/src/runtime/console.rs | 82 ++++--- core/src/runtime/mod.rs | 1 + 33 files changed, 1241 insertions(+), 869 deletions(-) create mode 100644 core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs create mode 100644 core/src/metadata/declarations/delegate_declaration/generic_delegate_instance_declaration.rs delete mode 100644 core/src/metadata/declarations/interface_declaration.rs create mode 100644 core/src/metadata/declarations/interface_declaration/generic_interface_declaration.rs create mode 100644 core/src/metadata/declarations/interface_declaration/generic_interface_instance_declaration.rs create mode 100644 core/src/metadata/declarations/interface_declaration/mod.rs create mode 100644 core/src/runtime/com/mod.rs diff --git a/core-bindings/build.rs b/core-bindings/build.rs index 2ab022e..ca42594 100644 --- a/core-bindings/build.rs +++ b/core-bindings/build.rs @@ -37,6 +37,7 @@ fn main() { .clang_arg("-std=c++17") .clang_args(&["-x", "c++"]) .clang_arg("-v") + .whitelist_function("RoResolveNamespace") .whitelist_function("Rometadataresolution_.*") .whitelist_function("IMetaDataImport2_.*") .whitelist_function("Enums_.*") diff --git a/core-bindings/src/bindings.cpp b/core-bindings/src/bindings.cpp index 9fb0e24..89327ce 100644 --- a/core-bindings/src/bindings.cpp +++ b/core-bindings/src/bindings.cpp @@ -82,8 +82,22 @@ Rometadataresolution_Ro_Locator(HRESULT(*fn)(PCWSTR name, IRoSimpleMetaDataBuild locator->locator = Ro::Locator(fn); } +/* +extern "C" void +Rometadataresolution_RoResolveNamespace(const HSTRING name, + const HSTRING windowsMetaDataDir, + const DWORD packageGraphDirsCount, + const HSTRING * packageGraphDirs, + DWORD * metaDataFilePathsCount, + HSTRING * *metaDataFilePaths, + DWORD * subNamespacesCount, + HSTRING * *subNamespaces) { + RoResolveNamespace() +} +*/ + extern "C" HRESULT IMetaDataImport2_GetMethodProps(void *metadata, mdMethodDef tkMethodDef, mdTypeDef *ptkClass, @@ -506,6 +520,10 @@ extern "C" void Helpers_toString_length(PCWSTR value, size_t * count) { } +extern "C" BOOL Helpers_IsTdSealed(DWORD value) { + return IsTdSealed(value); +} + /* extern "C" HRESULT GenericInstanceIdBuilder_locatorImpl(PCWSTR name, iro_simple_meta_data_builder & builder) { diff --git a/core/src/bindings.rs b/core/src/bindings.rs index 61903e7..f6d71e7 100644 --- a/core/src/bindings.rs +++ b/core/src/bindings.rs @@ -1,5 +1,22 @@ use crate::prelude::*; + +pub(crate) fn ro_resolve_namespace(name: HSTRING, + windows_meta_data_dir: Option, + package_graph_dirs_count: DWORD, + package_graph_dirs: Option<*const HSTRING>, + meta_data_file_paths_count: Option<*mut DWORD>, + meta_data_file_paths: Option<*mut *mut HSTRING>, + sub_namespaces_count: *mut DWORD, + sub_namespaces: Option<*mut *mut HSTRING>, +) -> HRESULT { + unsafe { + core_bindings::RoResolveNamespace( + name, windows_meta_data_dir.unwrap_or(0 as _), package_graph_dirs_count, package_graph_dirs.unwrap_or(0 as _), meta_data_file_paths_count.unwrap_or(0 as _), meta_data_file_paths.unwrap_or(0 as _), sub_namespaces_count, sub_namespaces.unwrap_or(0 as _), + ) + } +} + pub mod rometadataresolution { use crate::prelude::*; use windows::{HRESULT, HSTRING}; @@ -35,7 +52,7 @@ pub mod rometadataresolution { name_element_count: UINT32, name_elements: *mut PCWSTR, fn_: ::core::option::Option< - unsafe extern "C" fn(name: PCWSTR, builder: *mut IRoSimpleMetaDataBuilder) -> HRESULT, + unsafe extern "C" fn(name: PCWSTR, builder: *mut IRoSimpleMetaDataBuilder) -> i32, >, iid: *mut GUID, p_extra: Option<*mut ROPARAMIIDHANDLE>, @@ -45,7 +62,7 @@ pub mod rometadataresolution { core_bindings::Rometadataresolution_RoGetParameterizedTypeInstanceIID( name_element_count, name_elements, - fn_ as _, + fn_, iid, p_extra.unwrap_or(0 as _), ) as u32 @@ -82,11 +99,10 @@ pub mod imeta_data_import2 { unsafe { HRESULT(core_bindings::IMetaDataImport2_GetTypeDefPropsNameSize(metadata, md_type_def, pch_type_def) as u32) } - //unsafe { IMetaDataImport2_GetTypeDefPropsNameSize(metadata, md_type_def, pch_type_def) } } pub(crate) fn get_field_props(metadata: *mut c_void, - mb: MdFieldDef, + mb: mdFieldDef, p_class: Option<*mut mdTypeDef>, sz_field: Option<*mut u16>, cch_field: Option, @@ -174,7 +190,7 @@ pub mod imeta_data_import2 { } - pub(crate) fn enum_params(metadata: *mut c_void, ph_enum: *mut HCORENUM, mb: MdMethodDef, r_params: *mut MdParamDef, c_max: ULONG, + pub(crate) fn enum_params(metadata: *mut c_void, ph_enum: *mut HCORENUM, mb: mdMethodDef, r_params: *mut mdParamDef, c_max: ULONG, pc_tokens: *mut ULONG) -> windows::HRESULT { unsafe { HRESULT(core_bindings::IMetaDataImport2_EnumParams(metadata, ph_enum, mb, r_params, c_max, pc_tokens) as u32) } } @@ -471,20 +487,20 @@ pub mod imeta_data_import2 { unsafe { HRESULT( core_bindings::IMetaDataImport2_GetEventProps( - meta: *mut ::core::ffi::c_void, - ev: mdEvent, - p_class: *mut mdTypeDef, - sz_event: LPCWSTR, - cch_event: ULONG, - pch_event: *mut ULONG, - pdw_event_flags: *mut DWORD, - ptk_event_type: *mut mdToken, - pmd_add_on: *mut mdMethodDef, - pmd_remove_on: *mut mdMethodDef, - pmd_fire: *mut mdMethodDef, - rmd_other_method: *mut mdMethodDef, - c_max: ULONG, - pc_other_method: *mut ULONG, + meta, + ev, + p_class.unwrap_or(0 as _), + sz_event.unwrap_or(0 as _), + cch_event.unwrap_or_default(), + pch_event.unwrap_or(0 as _), + pdw_event_flags.unwrap_or(0 as _), + ptk_event_type.unwrap_or(0 as _), + pmd_add_on.unwrap_or(0 as _), + pmd_remove_on.unwrap_or(0 as _), + pmd_fire.unwrap_or(0 as _), + rmd_other_method.unwrap_or(0 as _), + c_max.unwrap_or_default(), + pc_other_method.unwrap_or(0 as _), ) as u32 ) } @@ -678,7 +694,7 @@ pub mod helpers { } } - pub(crate) fn cor_sig_uncompress_token(p_data: PCCOR_SIGNATURE) -> MdToken { + pub(crate) fn cor_sig_uncompress_token(p_data: PCCOR_SIGNATURE) -> mdToken { unsafe { core_bindings::Helpers_CorSigUncompressToken(p_data) } @@ -743,13 +759,13 @@ pub mod helpers { pub(crate) fn is_td_interface(value: DWORD) -> bool { unsafe { - core_bindings::Helpers_IsTdInterface(value: DWORD) == 1 + core_bindings::Helpers_IsTdInterface(value) == 1 } } pub(crate) fn is_td_class(value: DWORD) -> bool { unsafe { - core_bindings::Helpers_IsTdClass(value: DWORD) == 1 + core_bindings::Helpers_IsTdClass(value) == 1 } } @@ -775,11 +791,14 @@ pub mod helpers { pub(crate) fn to_string_length(value: PCWSTR, count: *mut usize) { unsafe { - core_bindings::Helpers_toString_length(value: PCWSTR, count: *mut usize); + core_bindings::Helpers_toString_length(value, count); } } + pub(crate) fn is_td_sealed(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsTdSealed(value) == 1 } + } } diff --git a/core/src/enums.rs b/core/src/enums.rs index 73f934c..13f0eba 100644 --- a/core/src/enums.rs +++ b/core/src/enums.rs @@ -1,4 +1,7 @@ -use std::convert::TryFrom; +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + #[derive(Copy, Clone, PartialEq, Debug)] #[repr(C)] diff --git a/core/src/lib.rs b/core/src/lib.rs index 28280fc..d73b194 100755 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,4 +1,4 @@ -//pub mod runtime; +pub mod runtime; pub mod metadata; pub mod bindings; pub mod prelude; diff --git a/core/src/metadata/com_helpers.rs b/core/src/metadata/com_helpers.rs index debb2cc..b4200bb 100755 --- a/core/src/metadata/com_helpers.rs +++ b/core/src/metadata/com_helpers.rs @@ -5,23 +5,23 @@ use std::borrow::Cow; const GUID_ATTRIBUTE: &'static str = "Windows.Foundation.Metadata.GuidAttribute"; -pub fn get_string_value_from_blob(metadata: *mut c_void, signature: PCCOR_SIGNATURE) -> &str { +pub fn get_string_value_from_blob<'a>(metadata: *mut c_void, signature: PCCOR_SIGNATURE) -> Cow<'a, str> { debug_assert!(!metadata.is_null()); debug_assert!(!signature.is_null()); if signature as u8 == u8::MAX { - return ""; + return "".into(); } let size = helpers::cor_sig_uncompress_data(signature); let slice = unsafe { std::slice::from_raw_parts(signature as *mut u16, size as usize) }; - OsString::from_wide(slice).to_string_lossy().as_ref() + windows::HSTRING::from_wide(slice).to_string_lossy().into() } -pub fn get_unary_custom_attribute_string_value(metadata: *mut c_void, token: mdToken, attribute_name: &str) -> &str { +pub fn get_unary_custom_attribute_string_value<'a>(metadata: *mut c_void, token: mdToken, attribute_name: &str) -> Cow<'a, str> { debug_assert!(!metadata.is_null()); debug_assert!(token != mdTokenNil); debug_assert!(!attribute_name.is_null()); @@ -37,7 +37,7 @@ pub fn get_unary_custom_attribute_string_value(metadata: *mut c_void, token: mdT result.is_ok() ); if result.is_err() { - return ""; + return "".into(); } get_string_value_from_blob(metadata, data + 2) @@ -84,26 +84,29 @@ pub fn get_guid_attribute_value(metadata: *mut c_void, token: mdToken) -> GUID { guid } -pub fn getTypeName(metadata: *mut c_void, token: mdToken) -> &str { -debug_assert!(!metadata.is_null()); -ASSERT(token != mdTokenNil); - -identifier nameData; -ULONG nameLength{ 0 }; - -switch (TypeFromToken(token)) { -case mdtTypeDef: -ASSERT_SUCCESS(metadata->GetTypeDefProps(token, nameData.data(), nameData.size(), &nameLength, nullptr, nullptr)); -break; - -case mdtTypeRef: -ASSERT_SUCCESS(metadata->GetTypeRefProps(token, nullptr, nameData.data(), nameData.size(), &nameLength)); -break; +pub fn get_type_name<'a>(metadata: *mut c_void, token: mdToken) -> Cow<'a, str> { + debug_assert!(!metadata.is_null()); + debug_assert!(token != mdTokenNil); -default: -ASSERT_NOT_REACHED(); -} + let mut name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; + let mut name_length = 0; + match CorTokenType::from(enums::type_from_token(token)) { + CorTokenType::mdtTypeDef => { + debug_assert!(imeta_data_import2::get_type_def_props( + metadata, token, Some(name_data.as_mut_ptr()), Some(name_data.len() as u32), Some(&mut name_length), None, None, + ).is_ok()); + } + CorTokenType::mdtTypeRef => { + debug_assert!( + imeta_data_import2::get_type_ref_props( + metadata, token, None, Some(name_data.as_mut_ptr()), Some(name_data.len() as u32), Some(&mut name_length), + ).is_ok() + ); + } + _ => { + std::unreachable!() + } + } -wstring result{ nameData.data(), nameLength - 1 }; -return result; + OsString::from_wide(name_data[..name_length]).into() } \ No newline at end of file diff --git a/core/src/metadata/declaration_factory.rs b/core/src/metadata/declaration_factory.rs index 32bbf2f..ac42009 100644 --- a/core/src/metadata/declaration_factory.rs +++ b/core/src/metadata/declaration_factory.rs @@ -1,93 +1,163 @@ -use crate::prelude::*; -use crate::bindings::enums; -use crate::metadata::declarations::delegate_declaration::DelegateDeclaration; -use crate::bindings::rometadataresolution; +use std::sync::{Arc, Mutex}; + +use crate::bindings::{enums, helpers, imeta_data_import2}; use crate::metadata::com_helpers::resolve_type_ref; -use std::sync::Arc; +use crate::metadata::declarations::base_class_declaration::BaseClassDeclarationImpl; + +use crate::metadata::declarations::delegate_declaration::{DelegateDeclaration, DelegateDeclarationImpl}; +use crate::metadata::declarations::delegate_declaration::generic_delegate_instance_declaration::GenericDelegateInstanceDeclaration; +use crate::metadata::declarations::interface_declaration::generic_interface_instance_declaration::GenericInterfaceInstanceDeclaration; +use crate::prelude::*; use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; +#[derive(Clone, Debug)] pub struct DeclarationFactory {} impl DeclarationFactory { - pub fn make_delegate_declaration(metadata: *mut c_void, token: mdToken) -> DelegateDeclaration{ - match enums::type_from_token(token) as CorTokenType + pub fn make_delegate_declaration<'b>(metadata: *mut c_void, token: mdToken) -> Box { + match CorTokenType::from(enums::type_from_token(token)) { - CorTokenType::mdtTypeDef => DelegateDeclaration::new(metadata, token), + CorTokenType::mdtTypeDef => Box::new(DelegateDeclaration::new(metadata, token)), CorTokenType::mdtTypeRef => { let mut external_metadata = std::ptr::null_mut(); let mut external_delegate_token = mdTokenNil; - let is_resolved = resolve_type_ref(metadata, token, &mut external_metadata,&mut external_delegate_token); + let is_resolved = resolve_type_ref(metadata, token, &mut external_metadata, &mut external_delegate_token); debug_assert!(is_resolved); - DelegateDeclaration::new(external_metadata, external_delegate_token) + Box::new(DelegateDeclaration::new(external_metadata, external_delegate_token)) + } + CorTokenType::mdtTypeSpec => { + let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; + let mut signature_ptr = signature.as_ptr(); + let mut signature_size = 0; + debug_assert!( + imeta_data_import2::get_type_spec_from_token( + metadata, token, &mut signature_ptr, &mut signature_size, + ).is_ok() + ); + + let type1 = helpers::cor_sig_uncompress_element_type(signature.as_ptr()); + debug_assert!( + type1 == crate::enums::CorElementType::ElementTypeGenericinst + ); + + let type2 = helpers::cor_sig_uncompress_element_type(signature.as_ptr()); + debug_assert!( + type2 == crate::enums::CorElementType::ElementTypeClass + ); + + let open_generic_delegate_token = helpers::cor_sig_uncompress_token(signature.as_ptr()); + match CorTokenType::from(enums::type_from_token(open_generic_delegate_token)) { + CorTokenType::mdtTypeDef => { + Box::new(GenericDelegateInstanceDeclaration::new(metadata, open_generic_delegate_token, metadata, token)) + } + CorTokenType::mdtTypeRef => { + let mut external_metadata = std::ptr::null_mut(); + let external_metadata_ptr = &mut external_metadata; + let mut external_delegate_token = mdTokenNil; + + let is_resolved = resolve_type_ref( + metadata, open_generic_delegate_token, external_metadata_ptr, &mut external_delegate_token, + ); + + debug_assert!(is_resolved); + Box::new(GenericDelegateInstanceDeclaration::new(external_metadata, external_delegate_token, metadata, token)) + } + _ => { + std::unreachable!() + } + } } - CorTokenType::mdtTypeSpec => {} _ => { std::unreachable!() } } } - pub fn make_interface_declaration(metadata: *mut c_void, token: mdToken): { - - match enums::type_from_token(token){ - mdtTypeDef => { - return Some( - Arc::new( - InterfaceDeclaration::new(metadata, token) - ) + pub fn make_interface_declaration(metadata: *mut c_void, token: mdToken) -> Arc> { + match CorTokenType::from(enums::type_from_token(token)) { + CorTokenType::mdtTypeDef => { + Arc::new( + Mutex::new(InterfaceDeclaration::new(metadata, token)) ) } - } - switch (TypeFromToken(token)) { - case mdtTypeDef: { - return make_unique(metadata, token); - } + CorTokenType::mdtTypeRef => { + let mut external_metadata = std::ptr::null_mut(); + let external_metadata_ptr = &mut external_metadata; + let mut external_interface_token = mdTokenNil; - case mdtTypeRef: { - ComPtr externalMetadata; - mdTypeDef externalInterfaceToken{ mdTokenNil }; + let is_resolved = resolve_type_ref(metadata, token, external_metadata_ptr, &mut external_interface_token); - bool isResolved{ resolveTypeRef(metadata, token, externalMetadata.GetAddressOf(), &externalInterfaceToken) }; - ASSERT(isResolved); + debug_assert!(is_resolved); - return make_unique(externalMetadata.Get(), externalInterfaceToken); + Arc::new( + Mutex::new(InterfaceDeclaration::new( + external_metadata, external_interface_token, + )) + ) } - - case mdtTypeSpec: { - PCCOR_SIGNATURE signature{ nullptr }; - ULONG signatureSize{ 0 }; - ASSERT_SUCCESS(metadata->GetTypeSpecFromToken(token, &signature, &signatureSize)); - - CorElementType type1{ CorSigUncompressElementType(signature) }; - ASSERT(type1 == ELEMENT_TYPE_GENERICINST); - - CorElementType type2{ CorSigUncompressElementType(signature) }; - ASSERT(type2 == ELEMENT_TYPE_CLASS); - - mdToken openGenericDelegateToken{ CorSigUncompressToken(signature) }; - switch (TypeFromToken(openGenericDelegateToken)) { - case mdtTypeDef: { - return make_unique(metadata, openGenericDelegateToken, metadata, token); + CorTokenType::mdtTypeSpec => { + let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; + let mut signature_ptr = &mut signature.as_mut_ptr(); + let mut signature_size = 0; + debug_assert!( + imeta_data_import2::get_type_spec_from_token( + metadata, token, signature_ptr as *mut _ as *mut *const u8, &mut signature_size, + ).is_ok() + ); + + let type1 = helpers::cor_sig_uncompress_element_type(signature.as_ptr()); + debug_assert!( + type1 == crate::enums::CorElementType::ElementTypeGenericinst + ); + + let type2 = helpers::cor_sig_uncompress_element_type(signature.as_ptr()); + + debug_assert!( + type2 == crate::enums::CorElementType::ElementTypeClass + ); + let open_generic_delegate_token = helpers::cor_sig_uncompress_token(signature.as_ptr()); + + match CorTokenType::from(enums::type_from_token(token)) { + CorTokenType::mdtTypeSpec => match CorTokenType::from(enums::type_from_token(open_generic_delegate_token)) { + CorTokenType::mdtTypeDef => { + Arc::new( + Mutex::new(GenericInterfaceInstanceDeclaration::new( + metadata, open_generic_delegate_token, metadata, token, + )) + ) + } + CorTokenType::mdtTypeRef => { + let mut external_metadata = std::ptr::null_mut(); + let external_metadata_ptr = &mut external_metadata; + let mut external_delegate_token = mdTokenNil; + + let is_resolved = resolve_type_ref( + metadata, open_generic_delegate_token, external_metadata_ptr, &mut external_delegate_token, + ); + + debug_assert!( + is_resolved + ); + + Arc::new( + Mutex::new( + GenericInterfaceInstanceDeclaration::new( + external_metadata, external_delegate_token, metadata, token, + ) + ) + ) + } + _ => { + std::unreachable!() + } } - - case mdtTypeRef: { - ComPtr externalMetadata; - mdTypeDef externalDelegateToken{ mdTokenNil }; - - bool isResolved{ resolveTypeRef(metadata, openGenericDelegateToken, externalMetadata.GetAddressOf(), &externalDelegateToken) }; - ASSERT(isResolved); - - return make_unique(externalMetadata.Get(), externalDelegateToken, metadata, token); + _ => { + std::unreachable!() } - - default: - ASSERT_NOT_REACHED(); } - - break; } - - default: - ASSERT_NOT_REACHED(); + _ => { + std::unreachable!() + } } } } \ No newline at end of file diff --git a/core/src/metadata/declarations/base_class_declaration.rs b/core/src/metadata/declarations/base_class_declaration.rs index 6b12ff4..65b3baa 100644 --- a/core/src/metadata/declarations/base_class_declaration.rs +++ b/core/src/metadata/declarations/base_class_declaration.rs @@ -1,37 +1,41 @@ +use std::any::Any; +use std::borrow::Cow; + + +use std::sync::{Arc, Mutex}; + use crate::{ - prelude::*, - metadata::declarations::type_declaration::TypeDeclaration, - metadata::declarations::interface_declaration::InterfaceDeclaration, + bindings::imeta_data_import2, + metadata::declaration_factory::DeclarationFactory, + metadata::declarations::declaration::{Declaration, DeclarationKind}, + metadata::declarations::event_declaration::EventDeclaration, metadata::declarations::method_declaration::MethodDeclaration, metadata::declarations::property_declaration::PropertyDeclaration, - metadata::declarations::event_declaration::EventDeclaration, - bindings::imeta_data_import2, + metadata::declarations::type_declaration::TypeDeclaration, + prelude::*, }; -use crate::metadata::declarations::declaration::{DeclarationKind, Declaration}; +use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; -use crate::metadata::declaration_factory::DeclarationFactory; - -use std::str::FromStr; -use std::borrow::Cow; +#[derive(Clone)] pub struct BaseClassDeclaration<'a> { base: TypeDeclaration<'a>, - implemented_interfaces: Vec>, + implemented_interfaces: Vec>>, methods: Vec>, properties: Vec>, events: Vec>, } -impl BaseClassDeclaration { - fn make_implemented_interfaces_declarations(metadata: *mut c_void, token: mdTypeDef) { +impl<'a> BaseClassDeclaration<'a> { + fn make_implemented_interfaces_declarations(metadata: *mut c_void, token: mdTypeDef) -> Vec>> { let mut enumerator = std::ptr::null_mut(); - let enumer = &mut enumerator; + let enumerator_ptr = &mut enumerator; let mut count = 0; let mut tokens = [0; 1024]; debug_assert!( imeta_data_import2::enum_interface_impls( - metadata, enumer, Some(token), Some(tokens.as_mut_ptr()), Some(tokens.len() as u32), Some(&mut count), + metadata, enumerator_ptr, Some(token), Some(tokens.as_mut_ptr()), Some(tokens.len() as u32), Some(&mut count), ).is_ok() ); @@ -39,11 +43,12 @@ impl BaseClassDeclaration { imeta_data_import2::close_enum(metadata, enumerator); let mut result = Vec::new(); - for i in 0..count { + + for token in tokens.into_iter() { let mut interface_token = mdTokenNil; debug_assert!( imeta_data_import2::get_interface_impl_props( - metadata, tokens[i], None, Some(&mut interface_token), + metadata, *token, None, Some(&mut interface_token), ).is_ok() ); result.push( @@ -56,22 +61,23 @@ impl BaseClassDeclaration { result } - fn make_method_declarations(metadata: *mut c_void, token: mdTypeDef) -> Vec { - let enumerator = std::ptr::null_mut(); + fn make_method_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec> { + let mut enumerator = std::ptr::null_mut(); + let enumerator_ptr = &mut enumerator; let mut count = 0; let mut tokens = [0; 1024]; debug_assert!( imeta_data_import2::enum_methods( - metadata, enumerator, token, tokens.as_mut_ptr(), tokens.len(), &mut count, + metadata, enumerator_ptr, token, tokens.as_mut_ptr(), tokens.len() as u32, &mut count, ).is_ok() ); - debug_assert!(count < tokens.len() - 1); + debug_assert!(count < (tokens.len() - 1) as u32); imeta_data_import2::close_enum(metadata, enumerator); let mut result = Vec::new(); - for i in 0..count { - let method = MethodDeclaration::new(metadata, tokens[i]); + for token in tokens.iter() { + let method = MethodDeclaration::new(metadata, *token); if !method.is_exported() { continue; } @@ -81,25 +87,23 @@ impl BaseClassDeclaration { return result; } - fn make_property_declarations(metadata: *mut c_void, token: mdTypeDef) -> Vec { - let enumerator = std::ptr::null_mut(); + fn make_property_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec> { + let mut enumerator = std::ptr::null_mut(); + let enumerator_ptr = &mut enumerator; let mut count = 0; let mut tokens = [0; 1024]; - debug_assert!( - imeta_data_import2::enum_pr - ); debug_assert!( imeta_data_import2::enum_properties( - metadata, enumerator, token, tokens.as_mut_ptr(), tokens.len(), &mut count, + metadata, enumerator_ptr, token, tokens.as_mut_ptr(), tokens.len() as u32, &mut count, ).is_ok() ); - debug_assert!(count < tokens.len() - 1); + debug_assert!(count < (tokens.len() - 1) as u32); imeta_data_import2::close_enum(metadata, enumerator); let mut result = Vec::new(); - for i in 0..count { - let property = PropertyDeclaration::new(metadata, tokens[i]); + for token in tokens.iter() { + let property = PropertyDeclaration::new(metadata, *token); if !property.is_exported() { continue; } @@ -108,22 +112,23 @@ impl BaseClassDeclaration { result } - fn make_event_declarations(metadata: *mut c_void, token: mdTypeDef) -> Vec { - let enumerator = std::ptr::null_mut(); + fn make_event_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec> { + let mut enumerator = std::ptr::null_mut(); + let enumerator_ptr = &mut enumerator; let mut count = 0; let mut tokens = [0; 1024]; debug_assert!( imeta_data_import2::enum_events( - metadata, enumerator, token, tokens.as_mut_ptr(), tokens.len(), &mut count, + metadata, enumerator_ptr, token, tokens.as_mut_ptr(), tokens.len() as u32, &mut count, ).is_ok() ); - debug_assert!(count < tokens.len() - 1); + debug_assert!(count < (tokens.len() - 1) as u32); imeta_data_import2::close_enum(metadata, enumerator); let mut result = Vec::new(); - for i in 0..count { - let event = EventDeclaration::new(metadata, tokens[i]); + for token in tokens.iter() { + let event = EventDeclaration::new(metadata, *token); if !event.is_exported() { continue; } @@ -144,90 +149,117 @@ impl BaseClassDeclaration { } } -pub trait BaseClassDeclarationImpl { +pub trait BaseClassDeclarationImpl: Any { + fn as_any(&self) -> &dyn Any; + fn base(&self) -> &TypeDeclaration; - fn implemented_interfaces(&self) -> &Vec; + fn implemented_interfaces<'a>(&self) -> &Vec>; - fn methods(&self) -> &Vec; + fn methods<'a>(&self) -> &Vec>; - fn properties(&self) -> &Vec; + fn properties<'a>(&self) -> &Vec>; - fn events(&self) -> &Vec; + fn events<'a>(&self) -> &Vec>; - fn find_members_with_name(&self, name: &str) -> Vec { - debug_assert!(name); + fn find_members_with_name(&self, name: &str) -> Vec> { + debug_assert!(!name.is_empty()); - let mut result = Vec::new(); + let mut result: Vec> = Vec::new(); + + // let mut methods = self.find_methods_with_name(name).into_iter().map(|item| Box::new(item)).collect(); + // result.append(&mut methods); + + let mut methods = self.find_methods_with_name(name); + for method in methods.into_iter() { + result.push( + Box::new(method) + ); + } + + // let mut properties = self.properties().into_iter().filter(|prop| prop.full_name() == name).collect(); + // result.append(&mut properties); + + let mut properties = self.properties().clone(); - let mut methods: Vec = self.find_methods_with_name(name); - result.append(&mut methods); + for property in properties.into_iter() { + if property.full_name() == name { + result.push( + Box::new(property) + ); + } + } - let mut properties = self.properties().iter().filter(|prop| prop.full_name() == name).collect(); - result.append(&mut properties); + // let mut events = self.events().into_iter().filter(|event| event.full_name() == name).collect(); + // result.append(&mut events); - let mut events = self.events().iter().filter(|event| event.full_name() == name).collect(); - result.append(&mut events); + let mut events = self.events().clone(); + + for event in events { + if event.full_name() == name { + result.push( + Box::new(event) + ) + } + } return result; } - fn find_methods_with_name(&self, name: &str) -> Vec { - debug_assert!(name); + fn find_methods_with_name<'b>(&self, name: &str) -> Vec> { + debug_assert!(!name.is_empty()); - let enumerator = std::ptr::null_mut(); + let mut enumerator = std::ptr::null_mut(); + let enumerator_ptr = &mut enumerator; let mut method_tokens: Vec = vec![0; 1024]; let mut methods_count = 0; - let name = OsString::from_str(name).unwrap_or_default().to_wide(); + let name = windows::HSTRING::from(name); + let name = name.as_wide(); let base = self.base(); debug_assert!( imeta_data_import2::enum_methods_with_name( - base.metadata, base.token, enumerator, name.as_ptr(), - method_tokens.as_mut_ptr(), method_tokens.len(), &mut methods_count, + base.metadata, enumerator_ptr, base.token, name.as_ptr(), + method_tokens.as_mut_ptr(), method_tokens.len() as u32, &mut methods_count, ).is_ok() ); imeta_data_import2::close_enum(base.metadata, enumerator); - let mut result = Vec::new(); - for i in 0..methods_count { - let method_token = method_tokens[i]; - result.push( - MethodDeclaration::new(base.metadata, method_token) - ) - } - - return result; + method_tokens.into_iter().map(|method_token| MethodDeclaration::new(base.metadata, method_token)).collect() } } -impl BaseClassDeclarationImpl for BaseClassDeclaration { - fn base<'a>(&self) -> &TypeDeclaration<'a> { +impl<'a> BaseClassDeclarationImpl for BaseClassDeclaration<'a> { + fn as_any(&self) -> &dyn Any { + self + } + + fn base(&self) -> &TypeDeclaration<'a> { &self.base } - fn implemented_interfaces<'a>(&self) -> &Vec> { + fn implemented_interfaces(&self) -> &Vec>> { &self.implemented_interfaces } - fn methods<'a>(&self) -> &Vec> { + fn methods(&self) -> &Vec> { &self.methods } - fn properties<'a>(&self) -> &Vec> { + fn properties(&self) -> &Vec> { &self.properties } - fn events<'a>(&self) -> &Vec> { + fn events(&self) -> &Vec> { &self.events } } -impl Declaration for BaseClassDeclaration { - fn name<'a>(&self) -> Cow<'a, str> { +impl<'a> Declaration for BaseClassDeclaration<'a> { + fn name<'b>(&self) -> Cow<'b, str> { self.full_name() } - fn full_name<'a>(&self) -> Cow<'a, str> { + fn full_name<'b>(&self) -> Cow<'b, str> { self.base().full_name() } diff --git a/core/src/metadata/declarations/class_declaration.rs b/core/src/metadata/declarations/class_declaration.rs index f12c94d..ceffd20 100644 --- a/core/src/metadata/declarations/class_declaration.rs +++ b/core/src/metadata/declarations/class_declaration.rs @@ -1,29 +1,30 @@ -use crate::prelude::*; +use std::borrow::Cow; +use std::str::FromStr; +use std::sync::Arc; + use crate::{ - metadata::declarations::method_declaration::MethodDeclaration, - metadata::declarations::interface_declaration::InterfaceDeclaration + metadata::declarations::method_declaration::MethodDeclaration }; - use crate::bindings::{helpers, imeta_data_import2}; -use std::str::FromStr; +use crate::bindings::helpers::get_type_name; use crate::metadata::declaration_factory::DeclarationFactory; -use std::sync::Arc; use crate::metadata::declarations::base_class_declaration::{BaseClassDeclaration, BaseClassDeclarationImpl}; -use crate::metadata::declarations::declaration::DeclarationKind; -use crate::bindings::helpers::get_type_name; - +use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; +use crate::metadata::declarations::interface_declaration::interface_declaration::InterfaceDeclaration; +use crate::prelude::*; const DEFAULT_ATTRIBUTE:&'static str = "Windows.Foundation.Metadata.DefaultAttribute"; +#[derive(Clone, Debug)] pub struct ClassDeclaration<'a> { initializers: Vec>, - default_interface: InterfaceDeclaration<'a>, + default_interface: Option>, base: BaseClassDeclaration<'a> } -impl ClassDeclaration { +impl<'a> ClassDeclaration<'a> { - fn make_initializer_declarations(metadata: *mut c_void, token: mdTypeDef) -> Vec{ + fn make_initializer_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec>{ let mut enumerator = std::ptr::null_mut(); let enumerator_ptr = &mut enumerator; let mut count = 0; @@ -68,7 +69,7 @@ impl ClassDeclaration { return result; } - fn make_default_interface(metadata: *mut c_void, token: mdTypeDef) -> Option> { + fn make_default_interface(metadata: *mut c_void, token: mdTypeDef) -> Option> { let mut interface_impl_tokens = vec![0_1024]; let mut interface_impl_count = 0; let mut interface_enumerator = std::ptr::null_mut(); @@ -97,11 +98,7 @@ impl ClassDeclaration { metadata, interface_impl_token, None, Some(&mut interface_token) ).is_ok() ); - return Some( - Arc::new( - DeclarationFactory::make_interface_declaration(metadata, interface_token) - ) - ) + return DeclarationFactory::make_interface_declaration(metadata, interface_token) } } @@ -118,7 +115,7 @@ impl ClassDeclaration { } } - pub fn base_full_name(&self) -> &str { + pub fn base_full_name<'b>(&self) -> Cow<'b, str> { let mut parent_token = mdTokenNil; let base = self.base.base(); debug_assert!( @@ -130,19 +127,45 @@ impl ClassDeclaration { ) ); let mut name = [0_u16; MAX_IDENTIFIER_LENGTH]; - get_type_name(base.metadata, parent_token, name.as_mut_ptr(), count); - return getTypeName(_metadata.Get(), parent_token); + let count = get_type_name(base.metadata, parent_token, name.as_mut_ptr(), name.len() as u32); + OsString::from_wide(name[..count]).into() } pub fn default_interface(&self) -> &InterfaceDeclaration{ &self.default_interface } - pub fn is_instantiable(&self) -> bool {} + pub fn is_instantiable(&self) -> bool { + !self.initializers.is_empty() + } - pub fn is_sealed(&self) -> bool {} + pub fn is_sealed(&self) -> bool { + let mut flags = 0; + let base = self.base.base(); + debug_assert!( + imeta_data_import2::get_type_def_props( + base.metadata, base.token, None, None, None, Some(&mut flags), None + ).is_ok() + ); + helpers::is_td_sealed(flags) + } + + pub fn initializers(&self) -> &[MethodDeclaration<'a>] { + self.initializers.as_slice() + } +} + + +impl <'a> Declaration for ClassDeclaration <'a> { + fn name<'b>(&self) -> Cow<'b, str> { + self.base.name() + } + + fn full_name<'b>(&self) -> Cow<'b, str> { + self.base.full_name() + } - pub fn initializers(&self) -> { - // self.initializers.iter() + fn kind(&self) -> DeclarationKind { + self.base.kind() } } \ No newline at end of file diff --git a/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs b/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs new file mode 100644 index 0000000..ea78885 --- /dev/null +++ b/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs @@ -0,0 +1,66 @@ +use std::borrow::Cow; + +use core_bindings::{mdToken}; + +use crate::bindings::imeta_data_import2; +use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; +use crate::metadata::declarations::delegate_declaration::{DelegateDeclaration, DelegateDeclarationImpl}; +use crate::prelude::c_void; +use crate::metadata::declarations::method_declaration::MethodDeclaration; +use crate::metadata::declarations::type_declaration::TypeDeclaration; + +#[derive(Clone, Debug)] +pub struct GenericDelegateDeclaration<'a> { + base: DelegateDeclaration<'a>, +} + +impl<'a> GenericDelegateDeclaration<'a> { + pub fn new(metadata: *mut c_void, token: mdToken) -> Self { + Self { + base: DelegateDeclaration::new_overload( + DeclarationKind::GenericDelegate, metadata, token, + ) + } + } + + pub fn number_of_generic_parameters(&self) -> usize { + let mut count = 0; + + let mut enumerator = std::ptr::null_mut(); + let enumerator_ptr = &mut enumerator; + + debug_assert!( + imeta_data_import2::enum_generic_params(self.base.base.metadata, enumerator_ptr, self.base.base.token, None, None, None).is_ok() + ); + debug_assert!( + imeta_data_import2::count_enum(self.base.base.metadata, enumerator, &mut count).is_ok() + ); + imeta_data_import2::close_enum(self.base.base.metadata, enumerator); + + return count as usize; + } +} + +impl<'a> Declaration for GenericDelegateDeclaration<'a> { + fn name<'b>(&self) -> Cow<'b, str> { + self.base.name() + } + + fn full_name<'b>(&self) -> Cow<'b, str> { + self.base.full_name() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind() + } +} + +impl<'a> DelegateDeclarationImpl for GenericDelegateDeclaration<'a> { + fn base(&self) -> &TypeDeclaration { + &self.base.base + } + + fn invoke_method(&self) -> &MethodDeclaration { + &self.base.invoke_method + } +} \ No newline at end of file diff --git a/core/src/metadata/declarations/delegate_declaration/generic_delegate_instance_declaration.rs b/core/src/metadata/declarations/delegate_declaration/generic_delegate_instance_declaration.rs new file mode 100644 index 0000000..371c8cc --- /dev/null +++ b/core/src/metadata/declarations/delegate_declaration/generic_delegate_instance_declaration.rs @@ -0,0 +1,74 @@ +use std::borrow::Cow; + +use core_bindings::{mdTypeDef, mdTypeSpec}; + +use crate::bindings::{enums, imeta_data_import2}; +use crate::enums::CorTokenType; +use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; +use crate::metadata::declarations::delegate_declaration::{DelegateDeclaration, DelegateDeclarationImpl}; +use crate::metadata::generic_instance_id_builder::GenericInstanceIdBuilder; +use crate::metadata::signature::Signature; +use crate::prelude::{c_void, CLSID, MAX_IDENTIFIER_LENGTH, mdTypeSpecNil}; +use crate::metadata::declarations::method_declaration::MethodDeclaration; +use crate::metadata::declarations::type_declaration::TypeDeclaration; + +#[derive(Clone, Debug)] +pub struct GenericDelegateInstanceDeclaration<'a> { + base: DelegateDeclaration<'a>, + closed_token: mdTypeSpec, + closed_metadata: *mut c_void, +} + +impl<'a> GenericDelegateInstanceDeclaration<'a> { + pub fn new(open_metadata: *mut c_void, open_token: mdTypeDef, closed_metadata: *mut c_void, closed_token: mdTypeSpec) -> Self { + debug_assert!(!closed_metadata.is_null()); + debug_assert!(CorTokenType::from(enums::type_from_token(closed_token)) == CorTokenType::mdtTypeSpec); + debug_assert!(closed_token != mdTypeSpecNil); + + Self { + base: DelegateDeclaration::new_overload( + DeclarationKind::GenericDelegateInstance, open_metadata, open_token, + ), + closed_token, + closed_metadata, + } + } +} + +impl<'a> Declaration for GenericDelegateInstanceDeclaration<'a> { + fn name<'b>(&self) -> Cow<'b, str> { + self.base.name() + } + + fn full_name<'b>(&self) -> Cow<'b, str> { + let mut signature = vec![0_u8; MAX_IDENTIFIER_LENGTH]; + let mut sig = signature.as_ptr(); + let mut signature_size = 0; + debug_assert!( + imeta_data_import2::get_type_spec_from_token( + self.closed_metadata, self.closed_token, &mut sig, &mut signature_size, + ).is_ok() + ); + signature.resize(signature_size as usize, 0); + Signature::to_string(self.closed_metadata, sig).into() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind() + } +} + + +impl<'a> DelegateDeclarationImpl for GenericDelegateInstanceDeclaration<'a> { + fn base(&self) -> &TypeDeclaration { + &self.base.base + } + + fn id(&self) -> CLSID { + GenericInstanceIdBuilder::generate_id(self) + } + + fn invoke_method(&self) -> &MethodDeclaration<'a> { + &self.base.invoke_method + } +} \ No newline at end of file diff --git a/core/src/metadata/declarations/delegate_declaration/mod.rs b/core/src/metadata/declarations/delegate_declaration/mod.rs index ce60215..bb2394a 100644 --- a/core/src/metadata/declarations/delegate_declaration/mod.rs +++ b/core/src/metadata/declarations/delegate_declaration/mod.rs @@ -1,30 +1,46 @@ -use crate::prelude::*; -use crate::metadata::declarations::type_declaration::TypeDeclaration; -use crate::metadata::declarations::method_declaration::MethodDeclaration; -use crate::bindings::{imeta_data_import2, enums}; -use crate::metadata::declarations::declaration::{DeclarationKind, Declaration}; -use crate::metadata::com_helpers::get_guid_attribute_value; -use crate::metadata::signature::Signature; +use std::borrow::Cow; -const INVOKE_METHOD_NAME: &'static str = "Invoke"; +use crate::{ + bindings::{imeta_data_import2}, + metadata::com_helpers::get_guid_attribute_value, + metadata::declarations::declaration::{Declaration, DeclarationKind}, + metadata::declarations::method_declaration::MethodDeclaration, + metadata::declarations::type_declaration::TypeDeclaration, + prelude::*, +}; + + +pub mod generic_delegate_declaration; +pub mod generic_delegate_instance_declaration; + +const INVOKE_METHOD_NAME: &str = "Invoke"; pub fn get_invoke_method_token(meta_data: *mut c_void, token: mdTypeDef) -> mdMethodDef { let mut invoke_method_token = mdTokenNil; - let string = OsString::from(INVOKE_METHOD_NAME); + let string = windows::HSTRING::from(INVOKE_METHOD_NAME); debug_assert!( imeta_data_import2::find_method( - meta_data, token, string.to_wide().as_ptr(), None, 0, &mut invoke_method_token, - ) + meta_data, token, string.as_wide().as_ptr(), None, 0, &mut invoke_method_token, + ).is_ok() ); return invoke_method_token; } +pub trait DelegateDeclarationImpl { + fn base(&self) -> &TypeDeclaration; + fn id(&self) -> GUID { + get_guid_attribute_value(self.base().metadata, self.base().token) + } + fn invoke_method(&self) -> &MethodDeclaration; +} + +#[derive(Clone, Debug)] pub struct DelegateDeclaration<'a> { base: TypeDeclaration<'a>, invoke_method: MethodDeclaration<'a>, } -impl DelegateDeclaration { +impl<'a> DelegateDeclaration<'a> { pub fn new(metadata: *mut c_void, token: mdTypeDef) -> Self { Self::new_overload( DeclarationKind::Delegate, metadata, token, @@ -41,94 +57,14 @@ impl DelegateDeclaration { ), } } - - pub fn id(&self) -> GUID { - get_guid_attribute_value(self.base.metadata, self.base.token) - } - - pub fn invoke_method<'a>(&self) -> &MethodDeclaration<'a> { - &self.invoke_method - } -} - -pub struct GenericDelegateDeclaration<'a> { - base: DelegateDeclaration<'a>, -} - -impl GenericDelegateDeclaration { - pub fn new(metadata: *mut c_void, token: mdToken) -> Self { - Self { - base: DelegateDeclaration::new_overload( - DeclarationKind::GenericDelegate, metadata, token, - ) - } - } - - pub fn number_of_generic_parameters(&self) -> usize { - let mut count = 0; - - let mut enumerator = std::ptr::null_mut(); - let enumer = &mut enumerator; - - debug_assert!( - imeta_data_import2::enum_generic_params(self.base.base.metadata, enumer, self.base.base.token, None, None, None).is_ok() - ); - debug_assert!( - imeta_data_import2::count_enum(self.base.base.metadata, enumerator, &mut count).is_ok() - ); - imeta_data_import2::close_enum(self.base.base.metadata, enumerator); - - return count as usize; - } -} - -pub struct GenericDelegateInstanceDeclaration<'a> { - base: DelegateDeclaration<'a>, - closed_token: mdTypeSpec, - closed_metadata: *mut c_void, -} - -impl GenericDelegateInstanceDeclaration { - pub fn new(open_metadata: *mut c_void, open_token: mdTypeDef, closed_metadata: *mut c_void, closed_token: mdTypeSpec) -> Self { - - debug_assert!(!closed_metadata.is_null()); - debug_assert!(enums::type_from_token(closed_token) == CorTokenType::ComdtTypeSpec as u32); - debug_assert!(closed_token != mdTypeSpecNil); - - Self { - base: DelegateDeclaration::new_overload( - DeclarationKind::GenericDelegateInstance, open_metadata, open_token, - ), - closed_token, - closed_metadata, - } - } - -pub fn id(&self) -> CLSID { - GenericInstanceIdBuilder::generate_Id(self) -} -} - -impl Declaration for DelegateDeclaration { - fn name<'a>(&self) -> &'a str { - self.base.name() - } - - fn full_name<'a>(&self) -> &'a str { - self.base.full_name() - } - - fn kind(&self) -> DeclarationKind { - self.base.kind - } } -impl Declaration for GenericDelegateDeclaration { - fn name<'a>(&self) -> &'a str { +impl<'a> Declaration for DelegateDeclaration<'a> { + fn name<'b>(&self) -> Cow<'b, str> { self.base.name() } - fn full_name<'a>(&self) -> &'a str { + fn full_name<'b>(&self) -> Cow<'b, str> { self.base.full_name() } @@ -137,25 +73,13 @@ impl Declaration for GenericDelegateDeclaration { } } -impl Declaration for GenericDelegateInstanceDeclaration { - fn name<'a>(&self) -> &'a str { - self.base.name() - } - fn full_name<'a>(&self) -> &'a str { - let mut signature = vec![0_u8; MAX_IDENTIFIER_LENGTH]; - let mut sig = signature.as_ptr(); - let mut signature_size = 0; - debug_assert!( - imeta_data_import2::get_type_spec_from_token( - self.closed_metadata, self.closed_token,&mut sig,&mut signature_size - ) - ); - signature.resize(signature_size as usize, 0); - return Signature::to_string(self.closed_metadata, sig); +impl<'a> DelegateDeclarationImpl for DelegateDeclaration<'a> { + fn base(&self) -> &TypeDeclaration<'a> { + &self.base } - fn kind(&self) -> DeclarationKind { - self.base.kind + fn invoke_method(&self) -> &MethodDeclaration<'a> { + &self.invoke_method } } \ No newline at end of file diff --git a/core/src/metadata/declarations/enum_declaration.rs b/core/src/metadata/declarations/enum_declaration.rs index 29640d2..1ad6a6d 100644 --- a/core/src/metadata/declarations/enum_declaration.rs +++ b/core/src/metadata/declarations/enum_declaration.rs @@ -1,73 +1,73 @@ use crate::prelude::*; use crate::bindings::{ - imeta_data_import2, helpers + imeta_data_import2, helpers, }; use super::{ - declaration::{ - Declaration, - DeclarationKind, - }, - type_declaration::TypeDeclaration, + declaration::{ + Declaration, + DeclarationKind, + }, + type_declaration::TypeDeclaration, }; use std::borrow::Cow; #[derive(Debug)] pub struct EnumDeclaration<'a> { - base: TypeDeclaration<'a>, + base: TypeDeclaration<'a>, } -impl Declaration for EnumDeclaration { - fn is_exported(&self) -> bool { - self.base.is_exported() - } +impl<'a> Declaration for EnumDeclaration<'a> { + fn is_exported(&self) -> bool { + self.base.is_exported() + } - fn name<'a>(&self) -> Cow<'a, str> { - self.base.name() - } + fn name<'b>(&self) -> Cow<'b, str> { + self.base.name() + } - fn full_name<'a>(&self) -> Cow<'a, str> { - self.base.full_name() - } + fn full_name<'b>(&self) -> Cow<'b, str> { + self.base.full_name() + } - fn kind(&self) -> DeclarationKind { - self.base.kind - } + fn kind(&self) -> DeclarationKind { + self.base.kind + } } -impl EnumDeclaration { - pub fn new(metadata: *mut c_void, token: mdTypeDef) -> Self { - Self { - base: TypeDeclaration::new(DeclarationKind::Enum, metadata, token) - } - } +impl<'a> EnumDeclaration<'a> { + pub fn new(metadata: *mut c_void, token: mdTypeDef) -> Self { + Self { + base: TypeDeclaration::new(DeclarationKind::Enum, metadata, token) + } + } - pub fn type_<'a>(&self) -> Cow<'a, &[u8]>{ - let mut type_field = mdTokenNil; - let name_w = OsString::from(COR_ENUM_FIELD_NAME).to_wide(); - debug_assert!(imeta_data_import2::find_field( - self.base.metadata, self.base.token, - Some(name_w.as_ptr()), None, None, Some(&mut type_field) - ).is_ok()); - let mut signature = [0_u8;MAX_IDENTIFIER_LENGTH]; - let mut signature_size = 0; - debug_assert!( - imeta_data_import2::get_field_props( - self.base.metadata, - type_field, - None, None, None, None, None, - Some(&mut signature.as_mut_ptr() as _ as *mut *const u8), - Some(&mut signature_size), - None, None, None - ).is_ok() - ); + pub fn type_<'b>(&self) -> Cow<'b, &[u8]> { + let mut type_field = mdTokenNil; + let name_w = OsString::from(COR_ENUM_FIELD_NAME).to_wide(); + debug_assert!(imeta_data_import2::find_field( + self.base.metadata, self.base.token, + Some(name_w.as_ptr()), None, None, Some(&mut type_field), + ).is_ok()); + let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; + let mut signature_size = 0; + debug_assert!( + imeta_data_import2::get_field_props( + self.base.metadata, + type_field, + None, None, None, None, None, + Some(&mut signature.as_mut_ptr() as _ as *mut *const u8), + Some(&mut signature_size), + None, None, None, + ).is_ok() + ); - let header= helpers::cor_sig_uncompress_data(signature.as_ptr()); - debug_assert!( - header == CorCallingConvention::ImageCeeCsCallconvField as u32 - ); + let header = helpers::cor_sig_uncompress_data(signature.as_ptr()); + debug_assert!( + header == CorCallingConvention::ImageCeeCsCallconvField as u32 + ); - let result:&[u8] = &signature[0..signature_size]; + let result: &[u8] = &signature[0..signature_size]; - result.into() - } + result.into() + } } \ No newline at end of file diff --git a/core/src/metadata/declarations/event_declaration.rs b/core/src/metadata/declarations/event_declaration.rs index a6e4b97..1015bad 100644 --- a/core/src/metadata/declarations/event_declaration.rs +++ b/core/src/metadata/declarations/event_declaration.rs @@ -2,22 +2,23 @@ use crate::prelude::*; use crate::bindings::{imeta_data_import2, helpers}; use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; use crate::metadata::declarations::type_declaration::TypeDeclaration; -use std::sync::Arc; use crate::metadata::declarations::delegate_declaration::DelegateDeclaration; use crate::metadata::declarations::method_declaration::MethodDeclaration; use std::ffi::c_void; use crate::metadata::declaration_factory::DeclarationFactory; use std::borrow::Cow; +#[derive(Clone, Debug)] pub struct EventDeclaration<'a> { base: TypeDeclaration<'a>, - type_: Arc>, + // Arc ?? + type_: DelegateDeclaration<'a>, add_method: MethodDeclaration<'a>, remove_method: MethodDeclaration<'a>, } -impl EventDeclaration { - pub fn make_add_method(metadata: *mut c_void, token: mdEvent) -> MethodDeclaration { +impl<'a> EventDeclaration <'a> { + pub fn make_add_method<'b>(metadata: *mut c_void, token: mdEvent) -> MethodDeclaration<'b> { let mut add_method_token = mdTokenNil; debug_assert!( imeta_data_import2::get_event_props( @@ -29,7 +30,7 @@ impl EventDeclaration { MethodDeclaration::new(metadata, add_method_token) } - pub fn make_remove_method(metadata: *mut c_void, token: mdEvent) -> MethodDeclaration { + pub fn make_remove_method<'b>(metadata: *mut c_void, token: mdEvent) -> MethodDeclaration<'b> { let mut remove_method_token = mdTokenNil; debug_assert!( imeta_data_import2::get_event_props( @@ -40,10 +41,10 @@ impl EventDeclaration { ) ); - MethodDeclaration::new(metadata, removeMethodToken) + MethodDeclaration::new(metadata, remove_method_token) } - pub fn make_type(metadata: *mut c_void, token: mdEvent) -> DelegateDeclaration { + pub fn make_type<'b>(metadata: *mut c_void, token: mdEvent) -> DelegateDeclaration<'b> { let mut delegate_token = mdTokenNil; debug_assert!( imeta_data_import2::get_event_props( @@ -54,7 +55,6 @@ impl EventDeclaration { return DeclarationFactory::make_delegate_declaration(metadata, delegate_token); } - pub fn new(metadata: *mut c_void, token: mdEvent) -> Self { Self { base: TypeDeclaration::new(DeclarationKind::Event, metadata, token), @@ -76,7 +76,6 @@ impl EventDeclaration { &self.type_ } - pub fn add_method(&self) -> &MethodDeclaration { &self.add_method } @@ -86,7 +85,7 @@ impl EventDeclaration { } } -impl Declaration for EventDeclaration { +impl<'a> Declaration for EventDeclaration<'a> { fn is_exported(&self) -> bool { let mut flags = 0; debug_assert!( @@ -104,18 +103,18 @@ impl Declaration for EventDeclaration { return true; } - fn name<'a>(&self) -> Cow<'a, str> { + fn name<'b>(&self) -> Cow<'b, str> { self.full_name() } - fn full_name<'a>(&self) -> Cow<'a, str> { + fn full_name<'b>(&self) -> Cow<'b, str> { let mut name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; let mut name_data_length = 0; debug_assert!( imeta_data_import2::get_event_props( self.base.metadata, self.base.token, - None, Some(name_data.as_mut_ptr()), Some(name_data.len()), + None, Some(name_data.as_mut_ptr()), Some(name_data.len() as u32), Some(&mut name_data_length), None, None, None, None, None, None, None, None, ).is_ok() diff --git a/core/src/metadata/declarations/field_declaration.rs b/core/src/metadata/declarations/field_declaration.rs index 93c3f3c..1960889 100644 --- a/core/src/metadata/declarations/field_declaration.rs +++ b/core/src/metadata/declarations/field_declaration.rs @@ -2,60 +2,61 @@ use super::declaration::{Declaration, DeclarationKind}; use crate::prelude::*; use crate::bindings::{ - imeta_data_import2, - helpers, - enums + imeta_data_import2, + enums, }; -use std::marker; -use std::ffi::{OsString}; - -pub struct FieldDeclaration <'a>{ - pub kind: DeclarationKind, - pub metadata: *mut c_void, - pub token: mdFieldDef, - _marker: marker::PhantomData<&'a *const c_void> +use std::{ + marker, + ffi::{OsString}, + borrow::Cow, +}; + +#[derive(Clone, Debug)] +pub struct FieldDeclaration<'a> { + pub kind: DeclarationKind, + pub metadata: *mut c_void, + pub token: mdFieldDef, + _marker: marker::PhantomData<&'a *const c_void>, } -impl Declaration for FieldDeclaration { - - fn name<'b>(&self) -> &'b str { - return self.full_name(); - } - - fn full_name<'b>(&self) -> &'b str { - let mut full_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; - let mut length = 0; - debug_assert!(imeta_data_import2::get_field_props( - self.metadata, self.token, None, - Some(full_name_data.as_mut_ptr()), - Some(full_name_data.len() as u32), - Some(&mut length), - None,None, - None, None, - None,None - ).is_ok()); - - full_name_data.resize(length as usize, 0); - OsString::from_wide(name.as_slice()).to_string_lossy().as_ref() - } - - fn kind(&self) -> DeclarationKind{ - self.kind - } +impl<'a> Declaration for FieldDeclaration<'a> { + fn name<'b>(&self) -> Cow<'b, str> { + return self.full_name(); + } + + fn full_name<'b>(&self) -> Cow<'b, str> { + let mut full_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; + let mut length = 0; + debug_assert!(imeta_data_import2::get_field_props( + self.metadata, self.token, None, + Some(full_name_data.as_mut_ptr()), + Some(full_name_data.len() as u32), + Some(&mut length), + None, None, + None, None, + None, None, + ).is_ok()); + + OsString::from_wide(full_name_data[..length]).into() + } + + fn kind(&self) -> DeclarationKind { + self.kind + } } -impl FieldDeclaration { - pub fn new(kind: DeclarationKind, metadata: *mut c_void, token: mdFieldDef) -> Self { - let value = Self { - kind, - metadata, - token, - _marker: marker::PhantomData - }; - - assert!(value.metadata.is_not_null()); - assert!(enums::type_from_token(value.token) == CorTokenType::mdtFieldDef as u32); - assert!(value.token != mdFieldDefNil); - value - } +impl<'a> FieldDeclaration<'a> { + pub fn new(kind: DeclarationKind, metadata: *mut c_void, token: mdFieldDef) -> Self { + let value = Self { + kind, + metadata, + token, + _marker: marker::PhantomData, + }; + + assert!(value.metadata.is_not_null()); + assert!(enums::type_from_token(value.token) == CorTokenType::mdtFieldDef as u32); + assert!(value.token != mdFieldDefNil); + value + } } \ No newline at end of file diff --git a/core/src/metadata/declarations/interface_declaration.rs b/core/src/metadata/declarations/interface_declaration.rs deleted file mode 100644 index 80c20ef..0000000 --- a/core/src/metadata/declarations/interface_declaration.rs +++ /dev/null @@ -1,212 +0,0 @@ -use crate::prelude::*; -use crate::metadata::declarations::base_class_declaration::{BaseClassDeclaration, BaseClassDeclarationImpl, BaseClassDeclarationImp}; -use crate::metadata::declarations::event_declaration::EventDeclaration; -use crate::metadata::declarations::method_declaration::MethodDeclaration; -use crate::metadata::declarations::property_declaration::PropertyDeclaration; -use crate::metadata::declarations::type_declaration::TypeDeclaration; -use crate::metadata::declarations::declaration::{DeclarationKind, Declaration}; -use crate::bindings::{helpers, imeta_data_import2, enums}; -use crate::metadata::com_helpers::get_guid_attribute_value; -use std::borrow::Cow; -use crate::metadata::generic_instance_id_builder::GenericInstanceIdBuilder; -use crate::metadata::signature::Signature; - -pub struct InterfaceDeclaration<'a> { - base: BaseClassDeclaration<'a>, -} - -impl InterfaceDeclaration { - pub fn new(metadata: *mut c_void, token: mdToken) -> Self { - Self::new_with_kind( - DeclarationKind::Interface, metadata, token, - ) - } - - pub fn new_with_kind(kind: DeclarationKind, metadata: *mut c_void, token: mdToken) -> Self { - Self { - base: BaseClassDeclaration::new( - kind, metadata, token, - ) - } - } - - pub fn id(&self) -> GUID { - let base = self.base.base(); - get_guid_attribute_value(base.metadata, base.token) - } -} - -impl<'a> Declaration for InterfaceDeclaration { - fn name<'a>(&self) -> Cow<'a, str> { - self.base.name() - } - - fn full_name<'a>(&self) -> Cow<'a, str> { - self.base.full_name() - } - - fn kind(&self) -> DeclarationKind { - self.base.kind() - } -} - -impl<'a> BaseClassDeclarationImpl for InterfaceDeclaration { - fn base(&self) -> &TypeDeclaration<'a> { - self.base.base() - } - - fn implemented_interfaces(&self) -> &Vec> { - self.base.implemented_interfaces() - } - - fn methods(&self) -> &Vec> { - self.base.methods() - } - - fn properties(&self) -> &Vec> { - self.base.properties() - } - - fn events(&self) -> &Vec { - self.base.events() - } -} - -pub struct GenericInterfaceDeclaration<'a> { - base: InterfaceDeclaration<'a>, -} - -impl GenericInterfaceDeclaration { - pub fn new(metadata: *mut c_void, token: mdToken) -> Self { - Self { - base: InterfaceDeclaration::new_with_kind(DeclarationKind::GenericInterface, metadata, token) - } - } - - pub fn number_of_generic_parameters(&self) -> usize { - let mut count = 0; - let enumerator = std::ptr::null_mut(); - let base = self.base.base.base(); - debug_assert!( - imeta_data_import2::enum_generic_params( - base.metadata, enumerator, base.token, None, None, None, - ).is_ok() - ); - debug_assert!( - imeta_data_import2::count_enum(base.metadata, enumerator, &mut count).is_ok() - ); - - return count; - } - - pub fn id(&self) -> GUID { - self.base.id() - } -} - -impl<'a> BaseClassDeclarationImpl for GenericInterfaceDeclaration<'a> { - fn base(&self) -> &TypeDeclaration<'a> { - self.base.base() - } - - fn implemented_interfaces(&self) -> &Vec> { - self.base.implemented_interfaces() - } - - fn methods(&self) -> &Vec> { - self.base.methods() - } - - fn properties(&self) -> &Vec> { - self.base.properties() - } - - fn events(&self) -> &Vec { - self.base.events() - } -} - -impl<'a> Declaration for GenericInterfaceDeclaration { - fn name<'a>(&self) -> Cow<'a, str> { - self.base.name() - } - - fn full_name<'a>(&self) -> Cow<'a, str> { - self.base.full_name() - } - - fn kind(&self) -> DeclarationKind { - self.base.kind() - } -} - - -pub struct GenericInterfaceInstanceDeclaration<'a> { - base: InterfaceDeclaration<'a>, - closed_metadata: *mut c_void, - closed_token: mdTypeSpec, -} - -impl GenericInterfaceInstanceDeclaration { - pub fn new(open_metadata: *mut c_void, open_token: mdTypeDef, closed_metadata: *mut c_void, closed_token: mdTypeSpec) -> Self { - debug_assert!(!closed_metadata.is_null()); - debug_assert!(enums::type_from_token(closed_token) == CorTokenType::mdtTypeSpec); - debug_assert!(closed_token != mdTypeSpecNil); - - Self { - base: InterfaceDeclaration::new_with_kind( - DeclarationKind::GenericInterfaceInstance, open_metadata, open_token, - ), - closed_metadata, - closed_token, - } - } - pub fn id(&self) -> GUID { - return GenericInstanceIdBuilder::generate_id(self); - } -} - -impl<'a> BaseClassDeclarationImpl for GenericInterfaceInstanceDeclaration { - fn base(&self) -> &TypeDeclaration<'a> { - self.base.base() - } - - fn implemented_interfaces(&self) -> &Vec> { - self.base.implemented_interfaces() - } - - fn methods(&self) -> &Vec> { - self.base.methods() - } - - fn properties(&self) -> &Vec> { - self.base.properties() - } - - fn events(&self) -> &Vec> { - self.base.events() - } -} - -impl<'a> Declaration for GenericInterfaceInstanceDeclaration { - fn name<'a>(&self) -> Cow<'a, str> { - self.base.name() - } - - fn full_name<'a>(&self) -> Cow<'a, str> { - let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; - let mut signature_size = 0; - debug_assert!( - imeta_data_import2::get_type_spec_from_token( - self.closed_metadata, self.closed_token, signature.as_mut_ptr(), &mut signature_size, - ).is_ok() - ); - Signature::to_string( - self.closed_metadata, signature.as_ptr(), - ).into() - } - - fn kind(&self) -> DeclarationKind { - self.base.kind() - } -} \ No newline at end of file diff --git a/core/src/metadata/declarations/interface_declaration/generic_interface_declaration.rs b/core/src/metadata/declarations/interface_declaration/generic_interface_declaration.rs new file mode 100644 index 0000000..ee85458 --- /dev/null +++ b/core/src/metadata/declarations/interface_declaration/generic_interface_declaration.rs @@ -0,0 +1,83 @@ +use std::borrow::Cow; + +use core_bindings::{GUID, mdToken}; + +use crate::bindings::imeta_data_import2; +use crate::metadata::declarations::base_class_declaration::BaseClassDeclarationImpl; +use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; +use crate::metadata::declarations::event_declaration::EventDeclaration; +use crate::metadata::declarations::interface_declaration::interface_declaration::InterfaceDeclaration; +use crate::metadata::declarations::method_declaration::MethodDeclaration; +use crate::metadata::declarations::property_declaration::PropertyDeclaration; +use crate::metadata::declarations::type_declaration::TypeDeclaration; +use crate::prelude::c_void; + +#[derive(Clone, Debug)] +pub struct GenericInterfaceDeclaration<'a> { + base: InterfaceDeclaration<'a>, +} + +impl<'a> GenericInterfaceDeclaration<'a> { + pub fn new(metadata: *mut c_void, token: mdToken) -> Self { + Self { + base: InterfaceDeclaration::new_with_kind(DeclarationKind::GenericInterface, metadata, token) + } + } + + pub fn number_of_generic_parameters(&self) -> usize { + let mut count = 0; + let mut enumerator = std::ptr::null_mut(); + let enumerator_ptr = &mut enumerator; + let base = self.base.base.base(); + debug_assert!( + imeta_data_import2::enum_generic_params( + base.metadata, enumerator_ptr, base.token, None, None, None, + ).is_ok() + ); + debug_assert!( + imeta_data_import2::count_enum(base.metadata, enumerator, &mut count).is_ok() + ); + + return count as usize; + } + + pub fn id(&self) -> GUID { + self.base.id() + } +} + +impl<'a> BaseClassDeclarationImpl for GenericInterfaceDeclaration<'a> { + fn base(&self) -> &TypeDeclaration { + self.base.base() + } + + fn implemented_interfaces(&self) -> &Vec { + self.base.implemented_interfaces() + } + + fn methods(&self) -> &Vec { + self.base.methods() + } + + fn properties(&self) -> &Vec { + self.base.properties() + } + + fn events(&self) -> &Vec { + self.base.events() + } +} + +impl<'a> Declaration for GenericInterfaceDeclaration<'a> { + fn name<'b>(&self) -> Cow<'b, str> { + self.base.name() + } + + fn full_name<'b>(&self) -> Cow<'b, str> { + self.base.full_name() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind() + } +} diff --git a/core/src/metadata/declarations/interface_declaration/generic_interface_instance_declaration.rs b/core/src/metadata/declarations/interface_declaration/generic_interface_instance_declaration.rs new file mode 100644 index 0000000..be4a6bf --- /dev/null +++ b/core/src/metadata/declarations/interface_declaration/generic_interface_instance_declaration.rs @@ -0,0 +1,90 @@ +use std::borrow::Cow; + +use core_bindings::{GUID, mdTypeDef, mdTypeSpec}; + +use crate::{ + metadata::declarations::method_declaration::MethodDeclaration, + metadata::declarations::event_declaration::EventDeclaration, + metadata::declarations::declaration::{Declaration, DeclarationKind}, + metadata::declarations::base_class_declaration::BaseClassDeclarationImpl, + enums::CorTokenType, + bindings::{enums, imeta_data_import2}, + metadata::declarations::property_declaration::PropertyDeclaration, + metadata::declarations::type_declaration::TypeDeclaration, + metadata::generic_instance_id_builder::GenericInstanceIdBuilder, + metadata::signature::Signature, + prelude::*, + metadata::declarations::interface_declaration::InterfaceDeclaration +}; + +#[derive(Clone, Debug)] +pub struct GenericInterfaceInstanceDeclaration<'a> { + base: InterfaceDeclaration<'a>, + closed_metadata: *mut c_void, + closed_token: mdTypeSpec, +} + +impl<'a> GenericInterfaceInstanceDeclaration<'a> { + pub fn new(open_metadata: *mut c_void, open_token: mdTypeDef, closed_metadata: *mut c_void, closed_token: mdTypeSpec) -> Self { + debug_assert!(!closed_metadata.is_null()); + debug_assert!(CorTokenType::from(enums::type_from_token(closed_token)) == CorTokenType::mdtTypeSpec); + debug_assert!(closed_token != mdTypeSpecNil); + + Self { + base: InterfaceDeclaration::new_with_kind( + DeclarationKind::GenericInterfaceInstance, open_metadata, open_token, + ), + closed_metadata, + closed_token, + } + } + pub fn id(&self) -> GUID { + return GenericInstanceIdBuilder::generate_id(self); + } +} + +impl<'a> BaseClassDeclarationImpl for GenericInterfaceInstanceDeclaration<'a> { + fn base(&self) -> &TypeDeclaration { + self.base.base() + } + + fn implemented_interfaces(&self) -> &Vec { + self.base.implemented_interfaces() + } + + fn methods(&self) -> &Vec { + self.base.methods() + } + + fn properties(&self) -> &Vec { + self.base.properties() + } + + fn events(&self) -> &Vec { + self.base.events() + } +} + +impl<'a> Declaration for GenericInterfaceInstanceDeclaration<'a> { + fn name<'b>(&self) -> Cow<'b, str> { + self.base.name() + } + + fn full_name<'b>(&self) -> Cow<'b, str> { + let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; + let signature_ptr = &mut signature.as_ptr(); + let mut signature_size = 0; + debug_assert!( + imeta_data_import2::get_type_spec_from_token( + self.closed_metadata, self.closed_token, signature_ptr, &mut signature_size, + ).is_ok() + ); + Signature::to_string( + self.closed_metadata, signature.as_ptr(), + ).into() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind() + } +} diff --git a/core/src/metadata/declarations/interface_declaration/mod.rs b/core/src/metadata/declarations/interface_declaration/mod.rs new file mode 100644 index 0000000..6a0401d --- /dev/null +++ b/core/src/metadata/declarations/interface_declaration/mod.rs @@ -0,0 +1,80 @@ +use std::borrow::Cow; + + +use crate::metadata::com_helpers::get_guid_attribute_value; +use crate::metadata::declarations::base_class_declaration::{BaseClassDeclaration, BaseClassDeclarationImpl}; +use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; +use crate::metadata::declarations::event_declaration::EventDeclaration; +use crate::metadata::declarations::method_declaration::MethodDeclaration; +use crate::metadata::declarations::property_declaration::PropertyDeclaration; +use crate::metadata::declarations::type_declaration::TypeDeclaration; +use crate::prelude::*; + +pub mod generic_interface_instance_declaration; +pub mod generic_interface_declaration; + + +use core_bindings::{GUID, mdToken}; + + +#[derive(Clone, Debug)] +pub struct InterfaceDeclaration<'a> { + base: BaseClassDeclaration<'a>, +} + +impl<'a> InterfaceDeclaration<'a> { + pub fn new(metadata: *mut c_void, token: mdToken) -> Self { + Self::new_with_kind( + DeclarationKind::Interface, metadata, token, + ) + } + + pub fn new_with_kind(kind: DeclarationKind, metadata: *mut c_void, token: mdToken) -> Self { + Self { + base: BaseClassDeclaration::new( + kind, metadata, token, + ) + } + } + + pub fn id(&self) -> GUID { + let base = self.base.base(); + get_guid_attribute_value(base.metadata, base.token) + } +} + +impl<'a> Declaration for InterfaceDeclaration<'a> { + fn name<'b>(&self) -> Cow<'b, str> { + self.base.name() + } + + fn full_name<'b>(&self) -> Cow<'b, str> { + self.base.full_name() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind() + } +} + +impl<'a> BaseClassDeclarationImpl for InterfaceDeclaration<'a> { + fn base(&self) -> &TypeDeclaration { + self.base.base() + } + + fn implemented_interfaces(&self) -> &Vec { + self.base.implemented_interfaces() + } + + fn methods(&self) -> &Vec { + self.base.methods() + } + + fn properties(&self) -> &Vec { + self.base.properties() + } + + fn events(&self) -> &Vec { + self.base.events() + } +} diff --git a/core/src/metadata/declarations/method_declaration.rs b/core/src/metadata/declarations/method_declaration.rs index bf6f615..b2161e8 100644 --- a/core/src/metadata/declarations/method_declaration.rs +++ b/core/src/metadata/declarations/method_declaration.rs @@ -10,16 +10,18 @@ use crate::{ use crate::enums::CorCallingConvention; use crate::metadata::com_helpers::get_unary_custom_attribute_string_value; use crate::metadata::declarations::parameter_declaration::ParameterDeclaration; +use std::borrow::Cow; +#[derive(Clone, Debug)] pub struct MethodDeclaration <'a> { base: TypeDeclaration<'a>, parameters: Vec>, } -const OVERLOAD_ATTRIBUTE: &'static str = "Windows.Foundation.Metadata.OverloadAttribute"; -const DEFAULT_OVERLOAD_ATTRIBUTE: &'static str ="Windows.Foundation.Metadata.DefaultOverloadAttribute"; +const OVERLOAD_ATTRIBUTE: &str = "Windows.Foundation.Metadata.OverloadAttribute"; +const DEFAULT_OVERLOAD_ATTRIBUTE: &str ="Windows.Foundation.Metadata.DefaultOverloadAttribute"; -impl MethodDeclaration { +impl<'a> MethodDeclaration <'a> { pub fn new(metadata: *mut c_void, token: mdMethodDef) -> Self { debug_assert!(!metadata.is_null()); debug_assert!(enums::type_from_token(token) == CorTokenType::mdtMethodDef as u32); @@ -27,13 +29,13 @@ impl MethodDeclaration { let mut signature = std::ptr::null_mut(); - let mut sig = &signature; + let mut signature_ptr = &mut signature; let mut signature_size: ULONG = 0; debug_assert!( imeta_data_import2::get_method_props( metadata, token, None, None, None, - None,None,Some(sig as *mut const* u8), Some(&mut signature_size), + None,None,Some(signature), Some(&mut signature_size), None,None ).is_ok() ); @@ -50,9 +52,9 @@ impl MethodDeclaration { std::unimplemented!() } - let mut arguments_count = { helpers::cor_sig_uncompress_data(signature) }; + let mut arguments_count = { helpers::cor_sig_uncompress_data(signature as *const u8) }; - let return_type = Signature::consumeType(signature); + let return_type = Signature::consume_type(signature as *const u8); let mut parameters: Vec = Vec::new(); let mut parameter_enumerator = std::ptr::null_mut(); @@ -71,8 +73,8 @@ impl MethodDeclaration { start_index += 1; } - for i in start_index..parameters_count { - let sig_type = Signature::consume_type(signature); + for i in start_index..parameters_count as usize{ + let sig_type = Signature::consume_type(signature as *const u8); parameters.push( ParameterDeclaration::new( metadata, parameter_tokens[i], sig_type @@ -80,7 +82,9 @@ impl MethodDeclaration { ) } - ASSERT(startSignature + signatureSize == signature); + // todo + //debug_assert!(signature_size == signature); + //debug_assert!(start_signature + signature_size == signature); Self { base: TypeDeclaration::new(DeclarationKind::Method, metadata, token), @@ -135,12 +139,12 @@ impl MethodDeclaration { self.parameters.len() } - pub fn overload_name<'a>(&self) ->&'a str { + pub fn overload_name<'b>(&self) -> Cow<'b, str> { get_unary_custom_attribute_string_value(self.base.metadata, self.base.token, OVERLOAD_ATTRIBUTE) } pub fn is_default_overload(&self) -> bool { - let data = OsString::from(DEFAULT_OVERLOAD_ATTRIBUTE).to_wide(); + let data = windows::HSTRING::from(DEFAULT_OVERLOAD_ATTRIBUTE).as_wide(); let get_attribute_result = imeta_data_import2::get_custom_attribute_by_name( self.base.metadata, self.base.token, Some(data.as_ptr()),None,None ); @@ -149,7 +153,7 @@ return get_attribute_result.0 == 0; } } -impl Declaration for MethodDeclaration { +impl<'a> Declaration for MethodDeclaration<'a> { fn is_exported(&self) -> bool { let mut method_flags: DWORD = 0; debug_assert!( @@ -169,21 +173,21 @@ impl Declaration for MethodDeclaration { return true; } - fn name<'a>(&self) -> &'a str { + fn name<'b>(&self) -> Cow<'b, str> { self.full_name() } - fn full_name<'a>(&self) -> &'a str { + fn full_name<'b>(&self) -> Cow<'b, str>{ let mut name_length = 0; - let mut data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + let mut data = [0_u16; MAX_IDENTIFIER_LENGTH]; debug_assert!( imeta_data_import2::get_method_props( self.base.metadata, self.base.token, None, Some(data.as_mut_ptr()), Some(data.len() as u32), Some(&mut name_length), None, None, None, None, None ).is_ok() ); - data.resize(name_length as usize, 0); - OsString::from_wide(data.as_slice()).to_string_lossy().as_ref() + OsString::from_wide(&data[..name_length as usize]).to_string_lossy() + } fn kind(&self) -> DeclarationKind { diff --git a/core/src/metadata/declarations/namespace_declaration.rs b/core/src/metadata/declarations/namespace_declaration.rs index 27058b5..09f3398 100644 --- a/core/src/metadata/declarations/namespace_declaration.rs +++ b/core/src/metadata/declarations/namespace_declaration.rs @@ -1,16 +1,22 @@ -use crate::metadata::declarations::type_declaration::TypeDeclaration; -use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; +use crate::{ + prelude::*, + metadata::declarations::type_declaration::TypeDeclaration, + metadata::declarations::declaration::{Declaration, DeclarationKind} +}; use std::option::Option::Some; +use std::borrow::Cow; +use crate::bindings::ro_resolve_namespace; +#[derive(Clone, Debug)] pub struct NamespaceDeclaration<'a> { base: TypeDeclaration<'a>, - children: Vec<&'a str>, + children: Vec, full_name: &'a str } -impl Declaration for NamespaceDeclaration { - fn name(&self) -> String { +impl<'a> Declaration for NamespaceDeclaration<'a> { + fn name<'b>(&self) -> Cow<'b, str> { let mut fully_qualified_name = self.full_name().to_owned(); if let Some(index) = fully_qualified_name.find(".") { fully_qualified_name = fully_qualified_name.chars().skip(index + 1).collect() @@ -18,8 +24,8 @@ impl Declaration for NamespaceDeclaration { return fully_qualified_name; } - fn full_name<'a>(&self) -> &'a str { - self.full_name + fn full_name<'b>(&self) -> Cow<'b, str> { + self.full_name.into() } fn kind(&self) -> DeclarationKind { @@ -27,21 +33,80 @@ impl Declaration for NamespaceDeclaration { } } -impl NamespaceDeclaration { +impl <'a>NamespaceDeclaration <'a>{ + pub fn new(full_name: &str) -> Self { // ASSERT(fullName); + debug_assert!(!full_name.is_empty()); + + let mut namespaces_count = 0; + + // Grab size + unsafe { + ro_resolve_namespace( + std::mem::transmute( + windows::HSTRING::from(full_name) + ), + None, + 0, + None, + None, + None, + &mut namespaces_count, + None + ); + } + + + + let mut namespaces: Vec = Vec::with_capacity(namespaces_count as usize); + let namespaces_ptr = &mut namespaces.as_mut_ptr(); + + // https://docs.microsoft.com/en-us/windows/win32/api/rometadataresolution/nf-rometadataresolution-roresolvenamespace + // RoResolveNamespace gives incomplete results, find a better way. + + + let hr = ro_resolve_namespace( + unsafe { + std::mem::transmute( + windows::HSTRING::from(full_name) + ) + }, + None, + 0, + None, + None, + None, + &mut namespaces_count, + Some(namespaces_ptr as _) + ); + + + let children: Vec = unsafe { namespaces.into_iter().map(|val| { + std::mem::transmute::(val).to_string_lossy() + }).collect() }; + + + + // The search for the "Windows" namespace on Windows Phone 8.1 fails both on a device and on an emulator with corrupted metadata error. + + // if (FAILED(hr)) { + // return; + // } + + Self { base: TypeDeclaration::new( DeclarationKind::Namespace, std::ptr::null_mut(), - std::ptr::null_mut() + 0 ), - children: Vec::new(), + children, full_name } } - pub fn children<'a>(&self) -> &[&'a str] { + pub fn children(&self) -> &[String] { self.children.as_slice() } } \ No newline at end of file diff --git a/core/src/metadata/declarations/parameter_declaration.rs b/core/src/metadata/declarations/parameter_declaration.rs index 1a179af..2d22aa7 100644 --- a/core/src/metadata/declarations/parameter_declaration.rs +++ b/core/src/metadata/declarations/parameter_declaration.rs @@ -2,28 +2,28 @@ use crate::prelude::*; use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; use crate::metadata::declarations::type_declaration::TypeDeclaration; use crate::bindings::{ - enums, helpers, imeta_data_import2 + enums, helpers, imeta_data_import2, }; use crate::enums::CorElementType; +use std::borrow::Cow; - +#[derive(Clone, Debug)] pub struct ParameterDeclaration<'a> { base: TypeDeclaration<'a>, - parameter_type: PCCOR_SIGNATURE + parameter_type: PCCOR_SIGNATURE, } -impl ParameterDeclaration { - pub fn new(metadata: *mut c_void, token: mdParamDef, sig_type: PCCOR_SIGNATURE)-> Self { - +impl<'a> ParameterDeclaration<'a> { + pub fn new(metadata: *mut c_void, token: mdParamDef, sig_type: PCCOR_SIGNATURE) -> Self { debug_assert!(!metadata.is_null()); debug_assert!(enums::type_from_token(token) == CorTokenType::mdtParamDef as u32); debug_assert!(token != mdParamDefNil); Self { base: TypeDeclaration::new( - DeclarationKind::Parameter, metadata, token + DeclarationKind::Parameter, metadata, token, ), - parameter_type: sig_type + parameter_type: sig_type, } } pub fn is_out(&self) -> bool { @@ -31,22 +31,22 @@ impl ParameterDeclaration { } } -impl Declaration for ParameterDeclaration { - - fn name<'a>(&self) -> &'a str { +impl<'a> Declaration for ParameterDeclaration<'a> { + fn name<'b>(&self) -> Cow<'b, str> { self.full_name() } - fn full_name<'a>(&self) -> &'a str { - let mut full_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + fn full_name<'b>(&self) -> Cow<'b, str> { + let mut full_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; let mut length = 0; - assert!(imeta_data_import2::get_param_props(self.metadata, self.token, - None,None, - Some(full_name_data.as_mut_ptr()), Some(full_name_data.len() as u32), -Some(&mut length),None,None,None,None + assert!(imeta_data_import2::get_param_props(self.metadata, self.token, + None, None, + Some(full_name_data.as_mut_ptr()), Some(full_name_data.len() as u32), + Some(&mut length), None, None, None, None, ).is_ok()); - full_name_data.resize(length as usize, 0); - OsString::from_wide(name.as_slice()).to_string_lossy().as_ref() + OsString::from_wide( + full_name_data[..length] + ).into() } fn kind(&self) -> DeclarationKind { diff --git a/core/src/metadata/declarations/property_declaration.rs b/core/src/metadata/declarations/property_declaration.rs index bc5c1fc..5d66767 100644 --- a/core/src/metadata/declarations/property_declaration.rs +++ b/core/src/metadata/declarations/property_declaration.rs @@ -8,14 +8,16 @@ use crate::{ prelude::* }; use crate::enums::CorCallingConvention; +use std::borrow::Cow; +#[derive(Clone, Debug)] pub struct PropertyDeclaration <'a>{ base: FieldDeclaration<'a>, getter: MethodDeclaration<'a>, setter: Option> } -impl <'a> Declaration<'a> for PropertyDeclaration { +impl <'a> Declaration for PropertyDeclaration<'a> { fn is_exported(&self) -> bool { let mut property_flags = 0; debug_assert!( @@ -32,11 +34,11 @@ impl <'a> Declaration<'a> for PropertyDeclaration { true } - fn name<'a>(&self) -> &'a str { + fn name<'b>(&self) -> Cow<'b, str> { self.base.name() } - fn full_name<'a>(&self) -> &'a str { + fn full_name<'b>(&self) -> Cow<'b, str> { let mut full_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; let mut name_length = 0; debug_assert!( @@ -52,7 +54,7 @@ impl <'a> Declaration<'a> for PropertyDeclaration { ).is_ok() ); full_name_data.resize(name_length as usize, 0); - OsString::from_wide(full_name_data.as_slice()).to_string_lossy().as_ref() + OsString::from_wide(full_name_data.as_slice()).into() } fn kind(&self) -> DeclarationKind { @@ -60,9 +62,9 @@ impl <'a> Declaration<'a> for PropertyDeclaration { } } -impl PropertyDeclaration { +impl<'a> PropertyDeclaration<'a> { - fn make_getter(metadata: *mut c_void, token : mdProperty) -> MethodDeclaration { + fn make_getter<'b>(metadata: *mut c_void, token : mdProperty) -> MethodDeclaration<'b> { let mut getter_token = mdTokenNil; debug_assert!( imeta_data_import2::get_property_props( @@ -80,7 +82,7 @@ impl PropertyDeclaration { ) } - fn make_setter(metadata: *mut c_void, token : mdProperty) -> Option{ + fn make_setter<'b>(metadata: *mut c_void, token : mdProperty) -> Option>{ let mut setter_token = mdTokenNil; debug_assert!( @@ -93,7 +95,7 @@ impl PropertyDeclaration { ); - if setterToken == mdMethodDefNil { + if setter_token == mdMethodDefNil { return None; } @@ -104,7 +106,7 @@ impl PropertyDeclaration { pub fn new(metadata: *mut c_void, token: mdProperty) -> Self{ debug_assert!(metadata); debug_assert!(enums::type_from_token(token) == CorTokenType::mdtProperty as u32); - debug_assert(token != mdPropertyNil); + debug_assert!(token != mdPropertyNil); Self { base: FieldDeclaration::new( DeclarationKind::Property, metadata, token @@ -142,7 +144,7 @@ impl PropertyDeclaration { &self.getter } - pub fn setter<'a>(&self) -> Option<&MethodDeclaration<'a>> { + pub fn setter(&self) -> Option<&MethodDeclaration<'a>> { self.setter.as_ref() } } \ No newline at end of file diff --git a/core/src/metadata/declarations/struct_declaration.rs b/core/src/metadata/declarations/struct_declaration.rs index b9284bf..136475d 100644 --- a/core/src/metadata/declarations/struct_declaration.rs +++ b/core/src/metadata/declarations/struct_declaration.rs @@ -5,17 +5,18 @@ use crate::bindings::imeta_data_import2; use crate::metadata::declarations::struct_field_declaration::StructFieldDeclaration; use std::borrow::Cow; +#[derive(Clone, Debug)] pub struct StructDeclaration<'a> { base: TypeDeclaration<'a>, fields: Vec>, } -impl Declaration for StructDeclaration { - fn name<'a>(&self) -> Cow<'a, str> { +impl<'a> Declaration for StructDeclaration<'a> { + fn name<'b>(&self) -> Cow<'b, str> { self.base.name() } - fn full_name<'a>(&self) -> Cow<'a, str> { + fn full_name<'b>(&self) -> Cow<'b, str> { self.base.full_name() } @@ -24,7 +25,7 @@ impl Declaration for StructDeclaration { } } -impl StructDeclaration { +impl<'a> StructDeclaration<'a> { pub fn new(metadata: *mut c_void, token: mdTypeDef, ) -> Self { Self { @@ -43,7 +44,7 @@ impl StructDeclaration { self.fields.as_slice() } - fn make_field_declarations(metadata: *mut c_void, token: mdTypeDef) -> Vec { + fn make_field_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec> { let mut enumerator = std::ptr::null_mut(); let mut count = 0; let mut tokens = [0; 1024]; diff --git a/core/src/metadata/declarations/struct_field_declaration.rs b/core/src/metadata/declarations/struct_field_declaration.rs index 91e703e..de37c37 100644 --- a/core/src/metadata/declarations/struct_field_declaration.rs +++ b/core/src/metadata/declarations/struct_field_declaration.rs @@ -3,17 +3,18 @@ use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; use crate::metadata::declarations::field_declaration::FieldDeclaration; use crate::bindings::{imeta_data_import2, helpers}; use std::borrow::Cow; +use crate::metadata::declarations::type_declaration::TypeDeclaration; pub struct StructFieldDeclaration<'a> { base: FieldDeclaration<'a>, } -impl Declaration for StructFieldDeclaration { - fn name<'a>(&self) -> &'a str { +impl<'a> Declaration for StructFieldDeclaration <'a>{ + fn name<'b>(&self) -> Cow<'b, str> { self.base.name() } - fn full_name<'a>(&self) -> &'a str { + fn full_name<'b>(&self) -> Cow<'b, str> { self.base.full_name() } @@ -22,7 +23,10 @@ impl Declaration for StructFieldDeclaration { } } -impl StructFieldDeclaration { +impl<'a> StructFieldDeclaration<'a> { + pub fn base(&self)-> &FieldDeclaration { + &self.base + } pub fn new(metadata: *mut c_void, token: mdFieldDef) -> Self { Self { base: FieldDeclaration::new( @@ -33,7 +37,7 @@ impl StructFieldDeclaration { } } - pub fn type_<'a>(&self) -> Cow<'a, [u8]> { + pub fn type_<'b>(&self) -> Cow<'b, [u8]> { let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; let mut signature_size = 0; @@ -50,7 +54,8 @@ impl StructFieldDeclaration { header == CorCallingConvention::ImageCeeCsCallconvField as u32 ); - let result: [u8] = signature[..signature_size]; + let result = &signature[..signature_size as usize]; result.into() } -} \ No newline at end of file +} + diff --git a/core/src/metadata/declarations/type_declaration.rs b/core/src/metadata/declarations/type_declaration.rs index c003cb3..2475793 100644 --- a/core/src/metadata/declarations/type_declaration.rs +++ b/core/src/metadata/declarations/type_declaration.rs @@ -11,9 +11,7 @@ use std::marker; use std::ffi::{OsString}; use std::borrow::Cow; - - - +#[derive(Clone, Debug)] pub struct TypeDeclaration<'a> { pub kind: DeclarationKind, pub metadata: *mut c_void, @@ -22,7 +20,7 @@ pub struct TypeDeclaration<'a> { } -impl Declaration for TypeDeclaration { +impl<'a> Declaration for TypeDeclaration<'a> { fn is_exported(&self) -> bool { let mut flags: DWORD = 0; debug_assert!( @@ -38,7 +36,7 @@ impl Declaration for TypeDeclaration { return true; } - fn name<'a>(&self) -> Cow<'a, str> { + fn name<'b>(&self) -> Cow<'b, str> { let mut name = self.full_name().to_string(); let back_tick_index = name.find('`'); if let Some(index) = back_tick_index { @@ -63,7 +61,7 @@ impl Declaration for TypeDeclaration { name.into() } - fn full_name<'a>(&self) -> Cow<'a, str> { + fn full_name<'b>(&self) -> Cow<'b, str> { let mut full_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; let length = helpers::get_type_name(self.metadata, self.token, full_name_data.as_mut_ptr(), full_name_data.len() as u32); OsString::from_wide(&full_name_data[..length]).into() @@ -74,7 +72,7 @@ impl Declaration for TypeDeclaration { } } -impl TypeDeclaration { +impl<'a> TypeDeclaration<'a> { pub fn new(kind: DeclarationKind, metadata: *mut c_void, token: mdTypeDef) -> Self { let value = Self { kind, @@ -84,7 +82,7 @@ impl TypeDeclaration { }; assert!(!value.metadata.is_null()); - assert!(enums::type_from_token(value.token) == CorTokenType::mdtTypeDef as u32); + assert!(CorTokenType::from(enums::type_from_token(value.token)) == CorTokenType::mdtTypeDef); assert!(value.token != mdTypeDefNil); value } diff --git a/core/src/metadata/generic_instance_id_builder.rs b/core/src/metadata/generic_instance_id_builder.rs index 05faf0c..478be41 100644 --- a/core/src/metadata/generic_instance_id_builder.rs +++ b/core/src/metadata/generic_instance_id_builder.rs @@ -1,22 +1,26 @@ -use crate::prelude::*; -use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; -use crate::bindings::helpers; -use crate::metadata::meta_data_reader::MetadataReader; -pub struct GenericInstanceIdBuilder {} -pub use crate::bindings::{rometadataresolution, iro_simple_meta_data_builder}; + use core_bindings::GUID; + +pub use crate::bindings::{iro_simple_meta_data_builder, rometadataresolution}; +use crate::bindings::helpers; use crate::metadata::declarations::class_declaration::ClassDeclaration; -use std::sync::Arc; -use windows::HRESULT; -use crate::metadata::declarations::interface_declaration::{InterfaceDeclaration, GenericInterfaceDeclaration}; +use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; +use crate::metadata::declarations::delegate_declaration::{DelegateDeclaration, DelegateDeclarationImpl}; +use crate::metadata::declarations::delegate_declaration::generic_delegate_declaration::GenericDelegateDeclaration; use crate::metadata::declarations::enum_declaration::EnumDeclaration; -use crate::metadata::signature::Signature; +use crate::metadata::declarations::interface_declaration::generic_interface_declaration::GenericInterfaceDeclaration; use crate::metadata::declarations::struct_declaration::StructDeclaration; -use crate::metadata::declarations::delegate_declaration::{DelegateDeclaration, GenericDelegateDeclaration}; +use crate::metadata::meta_data_reader::MetadataReader; +use crate::metadata::signature::Signature; +use crate::prelude::*; +use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; + +#[derive(Debug)] +pub struct GenericInstanceIdBuilder {} impl GenericInstanceIdBuilder { - extern "C" fn locator_impl(name: PCWSTR, builder: *mut IRoSimpleMetaDataBuilder) -> windows::HRESULT { + extern "C" fn locator_impl(name: PCWSTR, builder: *mut IRoSimpleMetaDataBuilder) -> i32 { let declaration = MetadataReader::find_by_name_w(name); debug_assert!(declaration.is_some()); @@ -30,15 +34,15 @@ impl GenericInstanceIdBuilder { let default_interface = class_declaration.default_interface(); let default_interface_id = default_interface.id(); - let full_name = OsString::from(default_interface.full_name()); - let full_name_w = full_name.to_wide(); + let full_name = windows::HSTRING::from(default_interface.full_name()); + let full_name_w = full_name.as_wide(); debug_assert!( iro_simple_meta_data_builder::set_runtime_class_simple_default( builder, name, full_name_w.as_ptr(), &default_interface_id - ) + ).is_ok() ); - return HRESULT::from_win32(0) + return 0 } DeclarationKind::Interface => { let mut interface_declaration = declaration @@ -49,7 +53,7 @@ impl GenericInstanceIdBuilder { iro_simple_meta_data_builder::set_win_rt_interface( builder,interface_declaration_id ); - HRESULT::from_win32(0) + return 0 } DeclarationKind::GenericInterface => { let mut generic_interface_declaration = declaration @@ -61,7 +65,7 @@ impl GenericInstanceIdBuilder { builder, generic_interface_declaration.id(), generic_interface_declaration.number_of_generic_parameters() as u32 ).is_ok() ); - HRESULT::from_win32(0) + return 0 } DeclarationKind::Enum => { let mut enum_declaration = declaration @@ -69,18 +73,22 @@ impl GenericInstanceIdBuilder { .downcast_ref::() .unwrap(); let type_ = enum_declaration.type_().into_owned(); - let full_name_w = enum_declaration.full_name().to_owned().to_wide(); + let full_name = windows::HSTRING::from(enum_declaration.full_name().to_owned().as_ref()); + let full_name_w = full_name.as_wide(); let signature = Signature::to_string( std::ptr::null() as _, type_.as_ptr() ); - let signature_w = signature.to_wide(); + let signature = windows::HSTRING::from( + signature.to_owned().as_ref() + ); + let signature_w = signature.as_wide(); debug_assert!( iro_simple_meta_data_builder::set_enum( builder, full_name_w.as_ptr(), signature_w.as_ptr() ).is_ok() ); - HRESULT::from_win32(0) + return 0 } DeclarationKind::Struct => { @@ -91,23 +99,27 @@ impl GenericInstanceIdBuilder { let mut field_names = Vec::new(); for field in struct_declaration.fields().iter() { - field_names.push( - Signature::to_string( - field.base.metadata, field.type_() - ).to_wide().as_ptr() - ) + let field_type = field.type_().to_owned(); + let signature = Signature::to_string( + field.base().metadata, field_type.as_ptr() + ); + let signature = windows::HSTRING::from(signature.as_ref()); + + field_names.push(signature); } - let full_name = struct_declaration.full_name().into_owned().to_wide(); + let full_name = windows::HSTRING::from(struct_declaration.full_name().as_ref()); + let full_name_w = full_name.as_wide(); + let field_names = field_names.into_iter().map(|field| field.as_wide().as_ptr()).collect(); debug_assert!( iro_simple_meta_data_builder::set_struct( - builder, full_name.as_ptr(), + builder, full_name_w.as_ptr(), struct_declaration.size() as u32, field_names.as_ptr() ).is_ok() ); - HRESULT::from_win32(0) + return 0 } DeclarationKind::Delegate => { let mut delegate_declaration = declaration @@ -115,12 +127,13 @@ impl GenericInstanceIdBuilder { .downcast_ref::() .unwrap(); + debug_assert!( iro_simple_meta_data_builder::set_delegate( builder, delegate_declaration.id() ).is_ok() ); - HRESULT::from_win32(0) + return 0 } DeclarationKind::GenericDelegate => { let mut generic_delegate_declaration = declaration @@ -130,8 +143,9 @@ impl GenericInstanceIdBuilder { debug_assert!( iro_simple_meta_data_builder::set_parameterized_delegate( builder, generic_delegate_declaration.id(), generic_delegate_declaration.number_of_generic_parameters() as u32 - ) - ) + ).is_ok() + ); + return 0 } _ => { std::unreachable!() @@ -142,7 +156,9 @@ impl GenericInstanceIdBuilder { } pub fn generate_id(declaration: &dyn Declaration) -> GUID { - let mut declaration_full_name = declaration.full_name().into_owned().to_wide(); + let mut declaration_full_name = declaration.full_name().into_owned(); + let mut declaration_full_name = windows::HSTRING::from(declaration_full_name); + let mut declaration_full_name = declaration_full_name.as_wide(); let mut name_parts = [0_u16;MAX_IDENTIFIER_LENGTH]; let mut name_parts_count = 0; let mut name_parts_w = &mut name_parts.as_ptr(); @@ -152,8 +168,8 @@ impl GenericInstanceIdBuilder { let mut guid = GUID::default(); debug_assert!( rometadataresolution::ro_get_parameterized_type_instance_iid( - name_parts_count, namePartsW.as_mut_ptr(), Option(GenericInstanceIdBuilder::locator_impl), &mut guid, None - ) + name_parts_count, name_parts_w, Some(GenericInstanceIdBuilder::locator_impl), &mut guid, None + ).is_ok() ); return guid; diff --git a/core/src/metadata/meta_data_reader.rs b/core/src/metadata/meta_data_reader.rs index 8c764ba..a829631 100644 --- a/core/src/metadata/meta_data_reader.rs +++ b/core/src/metadata/meta_data_reader.rs @@ -1,22 +1,25 @@ -use crate::prelude::*; use std::sync::Arc; + +use windows::HSTRING; + +use crate::bindings::{enums, helpers, imeta_data_import2, rometadataresolution}; +use crate::metadata::declarations::class_declaration::ClassDeclaration; use crate::metadata::declarations::declaration::Declaration; -use crate::metadata::declarations::namespace_declaration::NamespaceDeclaration; +use crate::metadata::declarations::delegate_declaration::DelegateDeclaration; +use crate::metadata::declarations::delegate_declaration::generic_delegate_declaration::GenericDelegateDeclaration; use crate::metadata::declarations::enum_declaration::EnumDeclaration; -use crate::metadata::declarations::delegate_declaration::{GenericDelegateDeclaration, InterfaceDeclaration, DelegateDeclaration}; -use crate::bindings::{rometadataresolution, imeta_data_import2, helpers, enums}; -use windows::HSTRING; -use crate::metadata::declarations::declaration::DeclarationKind::GenericInterfaceInstance; +use crate::metadata::declarations::interface_declaration::generic_interface_declaration::GenericInterfaceDeclaration; +use crate::metadata::declarations::interface_declaration::interface_declaration::InterfaceDeclaration; +use crate::metadata::declarations::namespace_declaration::NamespaceDeclaration; use crate::metadata::declarations::struct_declaration::StructDeclaration; -use crate::metadata::declarations::class_declaration::ClassDeclaration; -use std::ffi::OsStr; -use crate::metadata::declarations::interface_declaration::{GenericInterfaceDeclaration, InterfaceDeclaration}; +use crate::prelude::*; -const WINDOWS: &'static src = "Windows"; -const SYSTEM_ENUM: &'static src = "System.Enum"; -const SYSTEM_VALUETYPE: &'static src = "System.ValueType"; -const SYSTEM_MULTICASTDELEGATE: &'static src = "System.MulticastDelegate"; +const WINDOWS: &str = "Windows"; +const SYSTEM_ENUM: &str = "System.Enum"; +const SYSTEM_VALUETYPE: &str = "System.ValueType"; +const SYSTEM_MULTICASTDELEGATE: &str = "System.MulticastDelegate"; +#[derive(Debug)] pub struct MetadataReader {} impl MetadataReader { @@ -44,7 +47,7 @@ impl MetadataReader { ); if get_metadata_file_result.is_err() { - if get_metadata_file_result == RO_E_METADATA_NAME_IS_NAMESPACE { + if get_metadata_file_result == windows::HRESULT::from_win32(RO_E_METADATA_NAME_IS_NAMESPACE as u32) { return Some( Arc::new(NamespaceDeclaration::new(full_name)) ); diff --git a/core/src/metadata/signature.rs b/core/src/metadata/signature.rs index a4b87c3..d1d0f40 100644 --- a/core/src/metadata/signature.rs +++ b/core/src/metadata/signature.rs @@ -1,13 +1,20 @@ +#![allow(non_upper_case_globals)] + use crate::prelude::*; use crate::bindings::helpers; -use crate::metadata::enums::CorElementType; +use std::borrow::Cow; + +const Guid: &str = "Guid"; + +#[derive(Debug)] pub struct Signature {} impl Signature { pub fn consume_type(signature: PCCOR_SIGNATURE) -> PCCOR_SIGNATURE { let start = signature; let element_type = helpers::cor_sig_uncompress_element_type(signature); + use crate::enums::CorElementType; match element_type { CorElementType::ElementTypeVoid | CorElementType::ElementTypeBoolean | @@ -36,17 +43,17 @@ impl Signature { Signature::consume_type(signature); start } - CorElementType::ElementTypeVar =>{ + CorElementType::ElementTypeVar => { helpers::cor_sig_uncompress_data(signature); start } - CorElementType::ElementTypeGenericinst =>{ + CorElementType::ElementTypeGenericinst => { helpers::cor_sig_uncompress_element_type(signature); helpers::cor_sig_uncompress_token(signature); let generic_arguments_count = helpers::cor_sig_uncompress_data(signature); for i in 0..generic_arguments_count { - Signature::consume_type(signature) + Signature::consume_type(signature); } start } @@ -60,67 +67,64 @@ impl Signature { } } - pub fn to_string<'a>(metadata: *mut c_void, signature: PCCOR_SIGNATURE) -> &'a str { + pub fn to_string<'a>(metadata: *mut c_void, signature: PCCOR_SIGNATURE) -> Cow<'a, str> { let element_type = helpers::cor_sig_uncompress_element_type(signature); - match element_type { - CorElementType::ElementTypeVoid => "Void", - CorElementType::ElementTypeBoolean => "Boolean", - CorElementType::ElementTypeChar => "Char16", - CorElementType::ElementTypeI1 => "Int8", - CorElementType::ElementTypeU1 => "UInt8", - CorElementType::ElementTypeI2 => "Int16", - CorElementType::ElementTypeU2 => "UInt16", - CorElementType::ElementTypeI4 => "Int32", - CorElementType::ElementTypeU4 => "UInt32", - CorElementType::ElementTypeI8 => "Int64", - CorElementType::ElementTypeU8 => "UInt64", - CorElementType::ElementTypeR4 => "Single", - CorElementType::ElementTypeR8 => "Double", - CorElementType::ElementTypeString => "String", + use crate::enums::CorElementType; + return match element_type { + CorElementType::ElementTypeVoid => "Void".into(), + CorElementType::ElementTypeBoolean => "Boolean".into(), + CorElementType::ElementTypeChar => "Char16".into(), + CorElementType::ElementTypeI1 => "Int8".into(), + CorElementType::ElementTypeU1 => "UInt8".into(), + CorElementType::ElementTypeI2 => "Int16".into(), + CorElementType::ElementTypeU2 => "UInt16".into(), + CorElementType::ElementTypeI4 => "Int32".into(), + CorElementType::ElementTypeU4 => "UInt32".into(), + CorElementType::ElementTypeI8 => "Int64".into(), + CorElementType::ElementTypeU8 => "UInt64".into(), + CorElementType::ElementTypeR4 => "Single".into(), + CorElementType::ElementTypeR8 => "Double".into(), + CorElementType::ElementTypeString => "String".into(), CorElementType::ElementTypeValuetype => { let token = helpers::cor_sig_uncompress_token(signature); - let mut class_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + let mut class_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; let length = helpers::get_type_name(metadata, token, class_name_data.as_mut_ptr(), class_name_data.len() as u32); - class_name_data.resize(length as usize, 0); - let class_name = OsString::from_wide(name.as_slice()).to_string_lossy().as_ref(); + + let class_name = OsString::from_wide(&class_name_data[..length as usize]).to_string_lossy().as_ref(); if class_name.eq("System.Guid") { - "Guid" - }else { - class_name + Guid.into() + } else { + class_name.into() } } CorElementType::ElementTypeClass => { let token = helpers::cor_sig_uncompress_token(signature); - let mut class_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + let mut class_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; let length = helpers::get_type_name(metadata, token, class_name_data.as_mut_ptr(), class_name_data.len() as u32); - class_name_data.resize(length as usize, 0); - OsString::from_wide(name.as_slice()).to_string_lossy().as_ref() + OsString::from_wide(&class_name_data[..length as usize]).to_string_lossy() } - CorElementType::ElementTypeObject => "Object", + CorElementType::ElementTypeObject => "Object".into(), CorElementType::ElementTypeSzarray => { let result = Signature::to_string(metadata, signature); - result.to_owned() + "[]" + (result.to_owned() + "[]").into() } - CorElementType::ElementTypeVar =>{ + CorElementType::ElementTypeVar => { let index = helpers::cor_sig_uncompress_data(signature); - let mut result_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + let mut result_data = [0_u16; MAX_IDENTIFIER_LENGTH]; let length = helpers::to_wstring(index, result_data.as_mut_ptr()); - result_data.resize(length, 0); - "Var!".to_owned() + OsString::from_wide(result_data.as_slice()).to_string_lossy().as_ref() + ("Var!".to_owned() + OsString::from_wide(&result_data[..length as usize]).to_string_lossy().as_ref()).into() } CorElementType::ElementTypeGenericinst => { let generic_type = helpers::cor_sig_uncompress_element_type(signature); - assert(generic_type == CorElementType::ElementTypeClass); + debug_assert!(generic_type == CorElementType::ElementTypeClass); let token = helpers::cor_sig_uncompress_token(signature); - let mut class_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; + let mut class_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; let length = helpers::get_type_name(metadata, token, class_name_data.as_mut_ptr(), class_name_data.len() as u32); - class_name_data.resize(length as usize, 0); - - let mut result = OsString::from_wide(name.as_slice()).to_string_lossy().as_ref().to_owned(); + let mut result = OsString::from_wide(&class_name_data[..length as usize]).to_string_lossy().as_ref().to_owned(); result += "<"; @@ -128,7 +132,7 @@ impl Signature { for i in 0..generic_arguments_count { let sig_type = Signature::consume_type(signature); let data = Signature::to_string(metadata, sig_type); - result += data; + result += data.as_ref(); if i == generic_arguments_count - 1 { result += ", "; } @@ -136,16 +140,16 @@ impl Signature { result += ">"; - result + result.into() } CorElementType::ElementTypeByref => { let mut result = "ByRef ".to_owned(); - result += Signature::to_string(metadata, signature); - result + result += Signature::to_string(metadata, signature).as_ref(); + result.into() } _ => { std::unreachable!() } - } + }; } } \ No newline at end of file diff --git a/core/src/prelude.rs b/core/src/prelude.rs index 2d06d3c..a3f643e 100644 --- a/core/src/prelude.rs +++ b/core/src/prelude.rs @@ -6,6 +6,7 @@ pub use core_bindings::*; pub use std::ffi::{OsString}; pub use std::os::raw::{c_long, c_uint, c_void}; pub use libc::wchar_t; +pub use std::os::windows::ffi::*; pub const mdTokenNil: mdToken = Helpers_mdTokenNil; pub const mdModuleNil: mdToken = Helpers_mdModuleNil; @@ -37,7 +38,7 @@ pub use super::enums::*; pub type CLSID = GUID; -pub type RO_E_METADATA_NAME_IS_NAMESPACE = Helpers_RO_E_METADATA_NAME_IS_NAMESPACE; +pub const RO_E_METADATA_NAME_IS_NAMESPACE: HRESULT = Helpers_RO_E_METADATA_NAME_IS_NAMESPACE; pub const MAX_IDENTIFIER_LENGTH: usize = 511; diff --git a/core/src/runtime/com/mod.rs b/core/src/runtime/com/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/core/src/runtime/console.rs b/core/src/runtime/console.rs index 9f7cd7a..593358c 100755 --- a/core/src/runtime/console.rs +++ b/core/src/runtime/console.rs @@ -1,50 +1,48 @@ - use rusty_v8 as v8; -use bindings::{Windows::Win32::System::Console,Windows::Win32::System::WindowsProgramming}; +use core_bindings::{Windows::Win32::System::Console, Windows::Win32::System::WindowsProgramming}; use std::ffi::{CString, c_void}; -pub(crate) fn handle_console_log(scope: &mut v8::HandleScope, args: v8::FunctionCallbackArguments, _retval: v8::ReturnValue){ - let mut value = String::new(); - for i in 0..args.length() { - let item = args.get(i).to_rust_string_lossy(scope); - if i == args.length() - 1 { - value.push_str(&item) - } else { - value.push_str(&item); - value.push_str(",") - } - if i == args.length() - 1{ - value.push_str("\n"); - } - } - - let length = value.chars().count() as u32; - let handle = unsafe { WindowsProgramming::GetStdHandle(WindowsProgramming::STD_OUTPUT_HANDLE)}; - let string = CString::new(value).unwrap(); - let mut written = 0_u32; - unsafe { - Console::WriteConsoleA(handle, string.as_ptr() as *const c_void, length, &mut written, std::ptr::null_mut()); - } +pub(crate) fn handle_console_log(scope: &mut v8::HandleScope, args: v8::FunctionCallbackArguments, _retval: v8::ReturnValue) { + let mut value = String::new(); + for i in 0..args.length() { + let item = args.get(i).to_rust_string_lossy(scope); + if i == args.length() - 1 { + value.push_str(&item) + } else { + value.push_str(&item); + value.push_str(",") + } + if i == args.length() - 1 { + value.push_str("\n"); + } + } + let length = value.chars().count() as u32; + let handle = unsafe { WindowsProgramming::GetStdHandle(WindowsProgramming::STD_OUTPUT_HANDLE) }; + let string = CString::new(value).unwrap(); + let mut written = 0_u32; + unsafe { + Console::WriteConsoleA(handle, string.as_ptr() as *const c_void, length, &mut written, std::ptr::null_mut()); + } } -pub(crate) fn handle_console_dir(scope: &mut v8::HandleScope, args: v8::FunctionCallbackArguments, _retval: v8::ReturnValue){ - let mut value = String::new(); - for i in 0..args.length() { - let item = args.get(i).to_rust_string_lossy(scope); - if i == args.length() - 1 { - value.push_str(&item) - } else { - value.push_str(&item); - value.push_str(",") - } - } - let length = value.chars().count() as u32; - let handle = unsafe { WindowsProgramming::GetStdHandle(WindowsProgramming::STD_OUTPUT_HANDLE)}; +pub(crate) fn handle_console_dir(scope: &mut v8::HandleScope, args: v8::FunctionCallbackArguments, _retval: v8::ReturnValue) { + let mut value = String::new(); + for i in 0..args.length() { + let item = args.get(i).to_rust_string_lossy(scope); + if i == args.length() - 1 { + value.push_str(&item) + } else { + value.push_str(&item); + value.push_str(",") + } + } + let length = value.chars().count() as u32; + let handle = unsafe { WindowsProgramming::GetStdHandle(WindowsProgramming::STD_OUTPUT_HANDLE) }; - let string = CString::new(value).unwrap(); - let mut written = 0_u32; - unsafe { - Console::WriteConsoleA(handle, string.as_ptr() as *const c_void, length, &mut written, std::ptr::null_mut()); - } + let string = CString::new(value).unwrap(); + let mut written = 0_u32; + unsafe { + Console::WriteConsoleA(handle, string.as_ptr() as *const c_void, length, &mut written, std::ptr::null_mut()); + } } \ No newline at end of file diff --git a/core/src/runtime/mod.rs b/core/src/runtime/mod.rs index aebe0de..02863fa 100755 --- a/core/src/runtime/mod.rs +++ b/core/src/runtime/mod.rs @@ -1,6 +1,7 @@ mod global; mod ffi; mod console; +mod com; use rusty_v8 as v8; use std::ffi::{CString, CStr, c_void, OsStr, OsString}; From 29a3fa217222c9d033416371ddf9c9630d9d06db Mon Sep 17 00:00:00 2001 From: Osei Fortune Date: Wed, 9 Jun 2021 10:04:14 -0400 Subject: [PATCH 07/11] updates --- core-bindings/src/bindings.cpp | 147 ++++++++++------ core/src/bindings.rs | 166 +++++++++++++----- core/src/metadata/declaration_factory.rs | 8 +- .../declarations/base_class_declaration.rs | 21 +-- .../declarations/class_declaration.rs | 34 ++-- core/src/metadata/declarations/declaration.rs | 5 +- .../generic_delegate_declaration.rs | 2 +- .../generic_interface_declaration.rs | 4 +- .../declarations/method_declaration.rs | 4 +- .../declarations/namespace_declaration.rs | 2 +- .../declarations/struct_declaration.rs | 2 +- .../declarations/struct_field_declaration.rs | 3 +- .../metadata/declarations/type_declaration.rs | 4 +- .../declaring_interface_for_method.rs | 158 +++++++++++++++++ .../metadata/generic_instance_id_builder.rs | 46 +++-- core/src/metadata/meta_data_reader.rs | 30 ++-- core/src/metadata/mod.rs | 1 + core/src/runtime/console.rs | 4 +- core/src/runtime/mod.rs | 90 ---------- 19 files changed, 458 insertions(+), 273 deletions(-) create mode 100644 core/src/metadata/declaring_interface_for_method.rs diff --git a/core-bindings/src/bindings.cpp b/core-bindings/src/bindings.cpp index 89327ce..9b35a8b 100644 --- a/core-bindings/src/bindings.cpp +++ b/core-bindings/src/bindings.cpp @@ -27,7 +27,6 @@ Rometadataresolution_RoGetMetaDataFile(const HSTRING name, void *metaDataDispens return proc(name, dispenser, filePath, import, typeDefToken); */ - return RoGetMetaDataFile(name, dispenser, filePath, import, typeDefToken); } @@ -98,7 +97,7 @@ Rometadataresolution_RoResolveNamespace(const HSTRING name, */ -extern "C" HRESULT IMetaDataImport2_GetMethodProps(void *metadata, +extern "C" HRESULT IMetaDataImport2_GetMethodProps(IMetaDataImport2 *metadata, mdMethodDef tkMethodDef, mdTypeDef *ptkClass, LPWSTR szMethod, @@ -109,12 +108,11 @@ extern "C" HRESULT IMetaDataImport2_GetMethodProps(void *metadata, ULONG *pcbSigBlob, ULONG *pulCodeRVA, DWORD *pdwImplFlags) { - auto meta = static_cast(metadata); - return meta->GetMethodProps(tkMethodDef, ptkClass, szMethod, cchMethod, pchMethod, pdwAttr, ppvSigBlob, pcbSigBlob, + return metadata->GetMethodProps(tkMethodDef, ptkClass, szMethod, cchMethod, pchMethod, pdwAttr, ppvSigBlob, pcbSigBlob, pulCodeRVA, pdwImplFlags); } -extern "C" HRESULT IMetaDataImport2_GetPropertyProps(void *metadata, mdProperty prop, +extern "C" HRESULT IMetaDataImport2_GetPropertyProps(IMetaDataImport2 *metadata, mdProperty prop, mdTypeDef *pClass, LPCWSTR szProperty, ULONG cchProperty, @@ -130,8 +128,7 @@ extern "C" HRESULT IMetaDataImport2_GetPropertyProps(void *metadata, mdProperty mdMethodDef *rmdOtherMethod, ULONG cMax, ULONG *pcOtherMethod) { - auto meta = static_cast(metadata); - return meta->GetPropertyProps(prop, pClass, szProperty, cchProperty, pchProperty, pdwPropFlags, ppvSig, pbSig, + return metadata->GetPropertyProps(prop, pClass, szProperty, cchProperty, pchProperty, pdwPropFlags, ppvSig, pbSig, pdwCPlusTypeFlag, ppDefaultValue, pcchDefaultValue, pmdSetter, pmdGetter, rmdOtherMethod, cMax, pcOtherMethod); @@ -140,7 +137,7 @@ extern "C" HRESULT IMetaDataImport2_GetPropertyProps(void *metadata, mdProperty extern "C" HRESULT -IMetaDataImport2_GetFieldProps(void *metadata, +IMetaDataImport2_GetFieldProps(IMetaDataImport2 *metadata, mdFieldDef mb, mdTypeDef *pClass, LPWSTR szField, @@ -152,41 +149,41 @@ IMetaDataImport2_GetFieldProps(void *metadata, DWORD *pdwCPlusTypeFlag, UVCP_CONSTANT *ppValue, ULONG *pcchValue) { - auto meta = static_cast(metadata); - return meta->GetFieldProps(mb, pClass, szField, cchField, pchField, pdwAttr, ppvSigBlob, pcbSigBlob, + + return metadata->GetFieldProps(mb, pClass, szField, cchField, pchField, pdwAttr, ppvSigBlob, pcbSigBlob, pdwCPlusTypeFlag, ppValue, pcchValue); } extern "C" HRESULT -IMetaDataImport2_GetTypeDefProps(void *metadata, uint32_t mdTypeDef, LPWSTR szTypeDef, ULONG cchTypeDef, +IMetaDataImport2_GetTypeDefProps(IMetaDataImport2 *metadata, uint32_t mdTypeDef, LPWSTR szTypeDef, ULONG cchTypeDef, ULONG *pchTypeDef, DWORD *pdwTypeDefFlags, mdToken *ptkExtends) { - auto meta = static_cast(metadata); - return meta->GetTypeDefProps(mdTypeDef, szTypeDef, cchTypeDef, pchTypeDef, pdwTypeDefFlags, ptkExtends); + + return metadata->GetTypeDefProps(mdTypeDef, szTypeDef, cchTypeDef, pchTypeDef, pdwTypeDefFlags, ptkExtends); } -extern "C" HRESULT IMetaDataImport2_GetTypeDefPropsNameSize(void *metadata, uint32_t token, ULONG *pchTypeDef) { - auto meta = static_cast(metadata); +extern "C" HRESULT IMetaDataImport2_GetTypeDefPropsNameSize(IMetaDataImport2 *metadata, uint32_t token, ULONG *pchTypeDef) { + auto size = reinterpret_cast(&pchTypeDef); - return meta->GetTypeDefProps(token, 0, 0, size, 0, 0); + return metadata->GetTypeDefProps(token, 0, 0, size, 0, 0); } -extern "C" HRESULT IMetaDataImport2_EnumParams(void *metadata, HCORENUM *phEnum, +extern "C" HRESULT IMetaDataImport2_EnumParams(IMetaDataImport2 *metadata, HCORENUM *phEnum, mdMethodDef mb, mdParamDef *rParams, ULONG cMax, ULONG *pcTokens) { - auto meta = static_cast(metadata); - return meta->EnumParams(phEnum, mb, rParams, cMax, pcTokens); + + return metadata->EnumParams(phEnum, mb, rParams, cMax, pcTokens); } -extern "C" void IMetaDataImport2_CloseEnum(void *metadata, HCORENUM phEnum) { - auto meta = static_cast(metadata); - meta->CloseEnum(phEnum); +extern "C" void IMetaDataImport2_CloseEnum(IMetaDataImport2 *metadata, HCORENUM phEnum) { + + metadata->CloseEnum(phEnum); } -extern "C" HRESULT IMetaDataImport2_GetParamProps(void *metadata, +extern "C" HRESULT IMetaDataImport2_GetParamProps(IMetaDataImport2 *metadata, mdParamDef tk, mdMethodDef *pmd, ULONG *pulSequence, @@ -197,126 +194,126 @@ extern "C" HRESULT IMetaDataImport2_GetParamProps(void *metadata, DWORD *pdwCPlusTypeFlag, UVCP_CONSTANT *ppValue, ULONG *pcchValue) { - auto meta = static_cast(metadata); - return meta->GetParamProps(tk, pmd, pulSequence, szName, cchName, pchName, pdwAttr, pdwCPlusTypeFlag, ppValue, + + return metadata->GetParamProps(tk, pmd, pulSequence, szName, cchName, pchName, pdwAttr, pdwCPlusTypeFlag, ppValue, pcchValue); } -extern "C" HRESULT IMetaDataImport2_GetCustomAttributeByName(void *metadata, +extern "C" HRESULT IMetaDataImport2_GetCustomAttributeByName(IMetaDataImport2 *metadata, mdToken tkObj, LPCWSTR szName, const void **ppData, ULONG *pcbData) { - auto meta = static_cast(metadata); - return meta->GetCustomAttributeByName(tkObj, szName, ppData, pcbData); + + return metadata->GetCustomAttributeByName(tkObj, szName, ppData, pcbData); } -extern "C" HRESULT IMetaDataImport2_EnumInterfaceImpls(void *meta, HCORENUM *phEnum, +extern "C" HRESULT IMetaDataImport2_EnumInterfaceImpls(IMetaDataImport2 *metadata, HCORENUM *phEnum, mdTypeDef td, mdInterfaceImpl *rImpls, ULONG cMax, ULONG *pcImpls) { - auto metadata = reinterpret_cast(meta); + return metadata->EnumInterfaceImpls(phEnum, td, rImpls, cMax, pcImpls); } -extern "C" HRESULT IMetaDataImport2_GetTypeRefProps(void *meta, mdTypeRef tr, +extern "C" HRESULT IMetaDataImport2_GetTypeRefProps(IMetaDataImport2 *metadata, mdTypeRef tr, mdToken *ptkResolutionScope, LPWSTR szName, ULONG cchName, ULONG *pchName) { - auto metadata = reinterpret_cast(meta); + return metadata->GetTypeRefProps(tr, ptkResolutionScope, szName, cchName, pchName); } -extern "C" HRESULT IMetaDataImport2_FindMethod(void *meta, mdTypeDef td, +extern "C" HRESULT IMetaDataImport2_FindMethod(IMetaDataImport2 *metadata, mdTypeDef td, LPCWSTR szName, PCCOR_SIGNATURE pvSigBlob, ULONG cbSigBlob, mdMethodDef *pmb) { - auto metadata = reinterpret_cast(meta); + return metadata->FindMethod(td, szName, pvSigBlob, cbSigBlob, pmb); } -extern "C" HRESULT IMetaDataImport2_EnumGenericParams(void *meta, HCORENUM *phEnum, +extern "C" HRESULT IMetaDataImport2_EnumGenericParams(IMetaDataImport2 *metadata, HCORENUM *phEnum, mdToken tk, mdGenericParam rGenericParams[], ULONG cMax, ULONG *pcGenericParams) { - auto metadata = reinterpret_cast(meta); + return metadata->EnumGenericParams(phEnum, tk, rGenericParams, cMax, pcGenericParams); } -extern "C" HRESULT IMetaDataImport2_CountEnum(void *meta, HCORENUM hEnum, ULONG *pulCount) { - auto metadata = reinterpret_cast(meta); +extern "C" HRESULT IMetaDataImport2_CountEnum(IMetaDataImport2 *metadata, HCORENUM hEnum, ULONG *pulCount) { + return metadata->CountEnum(hEnum, pulCount); } -extern "C" HRESULT IMetaDataImport2_GetTypeSpecFromToken(void *meta, mdTypeSpec typespec, +extern "C" HRESULT IMetaDataImport2_GetTypeSpecFromToken(IMetaDataImport2 *metadata, mdTypeSpec typespec, PCCOR_SIGNATURE *ppvSig, ULONG *pcbSig) { - auto metadata = reinterpret_cast(meta); + return metadata->GetTypeSpecFromToken(typespec, ppvSig, pcbSig); } -extern "C" HRESULT IMetaDataImport2_EnumFields(void *meta, HCORENUM *phEnum, +extern "C" HRESULT IMetaDataImport2_EnumFields(IMetaDataImport2 *metadata, HCORENUM *phEnum, mdTypeDef tkTypeDef, mdFieldDef rgFields[], ULONG cMax, ULONG *pcTokens) { - auto metadata = reinterpret_cast(meta); + return metadata->EnumFields(phEnum, tkTypeDef, rgFields, cMax, pcTokens); } -extern "C" HRESULT IMetaDataImport2_EnumMethodsWithName(void *meta, HCORENUM *phEnum, +extern "C" HRESULT IMetaDataImport2_EnumMethodsWithName(IMetaDataImport2 *metadata, HCORENUM *phEnum, mdTypeDef tkTypeDef, LPCWSTR szName, mdMethodDef rgMethods[], ULONG cMax, ULONG *pcTokens) { - auto metadata = reinterpret_cast(meta); + return metadata->EnumMethodsWithName(phEnum, tkTypeDef, szName, rgMethods, cMax, pcTokens); } -extern "C" HRESULT IMetaDataImport2_GetInterfaceImplProps(void *meta, mdInterfaceImpl tkInterfaceImpl, +extern "C" HRESULT IMetaDataImport2_GetInterfaceImplProps(IMetaDataImport2 *metadata, mdInterfaceImpl tkInterfaceImpl, mdTypeDef *ptkClass, mdToken *ptkIface) { - auto metadata = reinterpret_cast(meta); + return metadata->GetInterfaceImplProps(tkInterfaceImpl, ptkClass, ptkIface); } -extern "C" HRESULT IMetaDataImport2_EnumMethods(void *meta, HCORENUM *phEnum, +extern "C" HRESULT IMetaDataImport2_EnumMethods(IMetaDataImport2 *metadata, HCORENUM *phEnum, mdTypeDef tkTypeDef, mdMethodDef rgMethods[], ULONG cMax, ULONG *pcTokens) { - auto metadata = reinterpret_cast(meta); + return metadata->EnumMethods(phEnum, tkTypeDef, rgMethods, cMax, pcTokens); } -extern "C" HRESULT IMetaDataImport2_EnumProperties(void *meta, HCORENUM *phEnum, +extern "C" HRESULT IMetaDataImport2_EnumProperties(IMetaDataImport2 *metadata, HCORENUM *phEnum, mdTypeDef tkTypDef, mdProperty rgProperties[], ULONG cMax, ULONG *pcProperties) { - auto metadata = reinterpret_cast(meta); + return metadata->EnumProperties(phEnum, tkTypDef, rgProperties, cMax, pcProperties); } -extern "C" HRESULT IMetaDataImport2_EnumEvents(void *meta, HCORENUM *phEnum, +extern "C" HRESULT IMetaDataImport2_EnumEvents(IMetaDataImport2 *metadata, HCORENUM *phEnum, mdTypeDef tkTypDef, mdEvent rgEvents[], ULONG cMax, ULONG *pcEvents) { - auto metadata = reinterpret_cast(meta); + return metadata->EnumEvents(phEnum, tkTypDef, rgEvents, cMax, pcEvents); } -extern "C" HRESULT IMetaDataImport2_GetEventProps(void *meta, mdEvent ev, +extern "C" HRESULT IMetaDataImport2_GetEventProps(IMetaDataImport2 *metadata, mdEvent ev, mdTypeDef *pClass, LPCWSTR szEvent, ULONG cchEvent, @@ -329,21 +326,55 @@ extern "C" HRESULT IMetaDataImport2_GetEventProps(void *meta, mdEvent ev, mdMethodDef rmdOtherMethod[], ULONG cMax, ULONG *pcOtherMethod) { - auto metadata = reinterpret_cast(meta); + return metadata->GetEventProps(ev, pClass, szEvent, cchEvent, pchEvent, pdwEventFlags, ptkEventType, pmdAddOn, pmdRemoveOn, pmdFire, rmdOtherMethod, cMax, pcOtherMethod); } -extern "C" HRESULT IMetaDataImport2_FindField(void* meta, mdTypeDef td, +extern "C" HRESULT IMetaDataImport2_FindField(IMetaDataImport2* metadata, mdTypeDef td, LPCWSTR szName, PCCOR_SIGNATURE pvSigBlob, ULONG cbSigBlob, mdFieldDef * pmb) { - auto metadata = reinterpret_cast(meta); return metadata->FindField(td, szName, pvSigBlob, cbSigBlob, pmb); } +extern "C" HRESULT IMetaDataImport2_GetMemberRefProps(IMetaDataImport2* metadata, mdMemberRef tkMemberRef, + mdToken * ptk, + LPWSTR szMember, + ULONG cchMember, + ULONG * pchMember, + PCCOR_SIGNATURE * ppvSigBlob, + ULONG * pcbSigBlob) { + return metadata->GetMemberRefProps(tkMemberRef, ptk, szMember, cchMember, pchMember, ppvSigBlob, pcbSigBlob); +} + +extern "C" HRESULT IMetaDataImport2_GetCustomAttributeProps(IMetaDataImport2* metadata, mdCustomAttribute cv, + mdToken * ptkObj, + mdToken * ptkType, + const BYTE * *ppBlob, + ULONG * pcbBlob) { + auto blob = reinterpret_cast(ppBlob); + return metadata->GetCustomAttributeProps(cv, ptkObj, ptkType, blob, pcbBlob); +} + +extern "C" HRESULT IMetaDataImport2_EnumCustomAttributes(IMetaDataImport2 * metadata, HCORENUM * phEnum, + mdToken tk, + mdToken tkType, + mdCustomAttribute rgCustomAttributes[], + ULONG cMax, + ULONG * pcCustomAttributes) { + return metadata->EnumCustomAttributes(phEnum, tk, tkType, rgCustomAttributes, cMax, pcCustomAttributes); +} + +extern "C" HRESULT IMetaDataImport2_FindTypeDefByName(IMetaDataImport2 * metadata, LPCWSTR szTypeDef, + mdToken tkEnclosingClass, + mdTypeDef * ptkTypeDef) { + return metadata->FindTypeDefByName(szTypeDef, tkEnclosingClass, ptkTypeDef); +} + + extern "C" HRESULT IRoSimpleMetaDataBuilder_SetRuntimeClassSimpleDefault(IRoSimpleMetaDataBuilder* builder, PCWSTR name, @@ -391,8 +422,8 @@ extern "C" ULONG32 Enums_TypeFromToken(mdToken token) { } -extern "C" ULONG Helpers_Get_Type_Name(void *meta, mdToken token, uint16_t *nameData, ULONG nameSize) { - auto metadata = reinterpret_cast(meta); +extern "C" ULONG Helpers_Get_Type_Name(IMetaDataImport2 *metadata, mdToken token, uint16_t *nameData, ULONG nameSize) { + ULONG nameLength{0}; auto data = reinterpret_cast(nameData); diff --git a/core/src/bindings.rs b/core/src/bindings.rs index f6d71e7..e201f4f 100644 --- a/core/src/bindings.rs +++ b/core/src/bindings.rs @@ -87,21 +87,19 @@ pub mod imeta_data_import2 { use core_bindings::*; use windows::HRESULT; - pub(crate) fn get_type_def_props(metadata: *mut c_void, md_type_def: c_uint, sz_type_def: Option, cch_type_def: Option, pch_type_def: Option<*mut ULONG>, pdw_type_def_flags: Option<*mut ULONG>, md_token: Option<*mut ULONG32>) -> HRESULT { + pub(crate) fn get_type_def_props(metadata: *mut IMetaDataImport2, md_type_def: c_uint, sz_type_def: Option, cch_type_def: Option, pch_type_def: Option<*mut ULONG>, pdw_type_def_flags: Option<*mut ULONG>, md_token: Option<*mut ULONG32>) -> HRESULT { unsafe { HRESULT(core_bindings::IMetaDataImport2_GetTypeDefProps(metadata, md_type_def, sz_type_def.unwrap_or(0 as _), cch_type_def.unwrap_or(0), pch_type_def.unwrap_or(&mut 0), pdw_type_def_flags.unwrap_or(0 as _), md_token.unwrap_or(&mut 0)) as u32) } - - //unsafe { IMetaDataImport2_GetTypeDefProps(metadata, md_type_def, sz_type_def.unwrap_or(std::ptr::null_mut()), cch_type_def.unwrap_or(0), pch_type_def.unwrap_or(&mut 0), pdw_type_def_flags, md_token.unwrap_or(&mut 0)) } } - fn get_type_def_props_name_size(metadata: *mut c_void, md_type_def: c_uint, pch_type_def: *mut ULONG) -> HRESULT { + fn get_type_def_props_name_size(metadata: *mut IMetaDataImport2, md_type_def: c_uint, pch_type_def: *mut ULONG) -> HRESULT { unsafe { HRESULT(core_bindings::IMetaDataImport2_GetTypeDefPropsNameSize(metadata, md_type_def, pch_type_def) as u32) } } - pub(crate) fn get_field_props(metadata: *mut c_void, + pub(crate) fn get_field_props(metadata: *mut IMetaDataImport2, mb: mdFieldDef, p_class: Option<*mut mdTypeDef>, sz_field: Option<*mut u16>, @@ -129,7 +127,7 @@ pub mod imeta_data_import2 { } } - pub(crate) fn get_property_props(metadata: *mut c_void, prop: mdProperty, p_class: Option<*mut mdTypeDef>, + pub(crate) fn get_property_props(metadata: *mut IMetaDataImport2, prop: mdProperty, p_class: Option<*mut mdTypeDef>, sz_property: Option<*mut u16>, cch_property: Option, pch_property: Option<*mut ULONG>, @@ -166,7 +164,7 @@ pub mod imeta_data_import2 { } } - pub(crate) fn get_method_props(metadata: *mut c_void, + pub(crate) fn get_method_props(metadata: *mut IMetaDataImport2, tk_method_def: mdMethodDef, ptk_class: Option<*mut mdTypeDef>, sz_method: Option<*mut u16>, @@ -190,18 +188,18 @@ pub mod imeta_data_import2 { } - pub(crate) fn enum_params(metadata: *mut c_void, ph_enum: *mut HCORENUM, mb: mdMethodDef, r_params: *mut mdParamDef, c_max: ULONG, + pub(crate) fn enum_params(metadata: *mut IMetaDataImport2, ph_enum: *mut HCORENUM, mb: mdMethodDef, r_params: *mut mdParamDef, c_max: ULONG, pc_tokens: *mut ULONG) -> windows::HRESULT { unsafe { HRESULT(core_bindings::IMetaDataImport2_EnumParams(metadata, ph_enum, mb, r_params, c_max, pc_tokens) as u32) } } - pub(crate) fn close_enum(metadata: *mut c_void, ph_enum: HCORENUM) { + pub(crate) fn close_enum(metadata: *mut IMetaDataImport2, ph_enum: HCORENUM) { unsafe { core_bindings::IMetaDataImport2_CloseEnum(metadata, ph_enum) } } - pub(crate) fn get_param_props(metadata: *mut c_void, tk: mdParamDef, + pub(crate) fn get_param_props(metadata: *mut IMetaDataImport2, tk: mdParamDef, pmd: Option<*mut mdMethodDef>, pul_sequence: Option<*mut ULONG>, sz_name: Option<*mut u16>, @@ -227,7 +225,7 @@ pub mod imeta_data_import2 { } } - pub(crate) fn get_custom_attribute_by_name(metadata: *mut c_void, + pub(crate) fn get_custom_attribute_by_name(metadata: *mut IMetaDataImport2, tk_obj: mdToken, sz_name: Option<*const u16>, pp_data: Option<*mut *const ::core::ffi::c_void>, @@ -241,7 +239,7 @@ pub mod imeta_data_import2 { } } - pub(crate) fn enum_interface_impls(metadata: *mut c_void, ph_enum: *mut HCORENUM, + pub(crate) fn enum_interface_impls(metadata: *mut IMetaDataImport2, ph_enum: *mut HCORENUM, td: Option, r_impls: Option<*mut mdInterfaceImpl>, c_max: Option, @@ -255,14 +253,14 @@ pub mod imeta_data_import2 { } } - pub(crate) fn get_type_ref_props(meta: *mut c_void, tr: mdTypeRef, + pub(crate) fn get_type_ref_props(metadata: *mut IMetaDataImport2, tr: mdTypeRef, ptk_resolution_scope: Option<*mut mdToken>, sz_name: Option<*mut u16>, cch_name: Option, pch_name: Option<*mut ULONG>) -> windows::HRESULT { unsafe { HRESULT( - core_bindings::IMetaDataImport2_GetTypeRefProps(meta, tr, + core_bindings::IMetaDataImport2_GetTypeRefProps(metadata, tr, ptk_resolution_scope.unwrap_or(0 as _), sz_name.unwrap_or(0 as _), cch_name.unwrap_or_default(), @@ -271,7 +269,7 @@ pub mod imeta_data_import2 { } } - pub(crate) fn find_method(meta: *mut c_void, + pub(crate) fn find_method(metadata: *mut IMetaDataImport2, td: mdTypeDef, sz_name: LPCWSTR, pv_sig_blob: Option, @@ -279,13 +277,13 @@ pub mod imeta_data_import2 { pmb: *mut mdMethodDef) -> windows::HRESULT { unsafe { HRESULT( - IMetaDataImport2_FindMethod(meta, td, sz_name, pv_sig_blob.unwrap_or(0 as _), cb_sig_blob, pmb) as u32 + IMetaDataImport2_FindMethod(metadata, td, sz_name, pv_sig_blob.unwrap_or(0 as _), cb_sig_blob, pmb) as u32 ) } } pub(crate) fn enum_generic_params( - meta: *mut c_void, + metadata: *mut IMetaDataImport2, ph_enum: *mut HCORENUM, tk: mdToken, r_generic_params: Option<*mut mdGenericParam>, @@ -295,7 +293,7 @@ pub mod imeta_data_import2 { unsafe { HRESULT( core_bindings::IMetaDataImport2_EnumGenericParams( - meta, + metadata, ph_enum, tk, r_generic_params.unwrap_or(0 as _), @@ -308,19 +306,19 @@ pub mod imeta_data_import2 { pub fn count_enum( - meta: *mut c_void, + metadata: *mut IMetaDataImport2, h_enum: HCORENUM, pul_count: *mut ULONG, ) -> HRESULT { unsafe { HRESULT( - core_bindings::IMetaDataImport2_CountEnum(meta, h_enum, pul_count) as u32 + core_bindings::IMetaDataImport2_CountEnum(metadata, h_enum, pul_count) as u32 ) } } pub fn get_type_spec_from_token( - meta: *mut c_void, + metadata: *mut IMetaDataImport2, typespec: mdTypeSpec, ppv_sig: *mut PCCOR_SIGNATURE, pcb_sig: *mut ULONG, @@ -328,7 +326,7 @@ pub mod imeta_data_import2 { unsafe { HRESULT( IMetaDataImport2_GetTypeSpecFromToken( - meta, + metadata, typespec, ppv_sig, pcb_sig, @@ -339,7 +337,7 @@ pub mod imeta_data_import2 { pub(crate) fn enum_fields( - meta: *mut c_void, + metadata: *mut IMetaDataImport2, ph_enum: *mut HCORENUM, tk_type_def: mdTypeDef, rg_fields: *mut mdFieldDef, @@ -349,7 +347,7 @@ pub mod imeta_data_import2 { unsafe { HRESULT( core_bindings::IMetaDataImport2_EnumFields( - meta, + metadata, ph_enum, tk_type_def, rg_fields, @@ -361,7 +359,7 @@ pub mod imeta_data_import2 { } pub(crate) fn enum_methods_with_name( - meta: *mut c_void, + metadata: *mut IMetaDataImport2, ph_enum: *mut HCORENUM, tk_type_def: mdTypeDef, sz_name: LPCWSTR, @@ -372,7 +370,7 @@ pub mod imeta_data_import2 { unsafe { HRESULT( core_bindings::IMetaDataImport2_EnumMethodsWithName( - meta, + metadata, ph_enum, tk_type_def, sz_name, @@ -385,7 +383,7 @@ pub mod imeta_data_import2 { } pub(crate) fn get_interface_impl_props( - meta: *mut ::core::ffi::c_void, + metadata: *mut IMetaDataImport2, tk_interface_impl: mdInterfaceImpl, ptk_class: Option<*mut mdTypeDef>, ptk_iface: Option<*mut mdToken>, @@ -393,7 +391,7 @@ pub mod imeta_data_import2 { unsafe { HRESULT( core_bindings::IMetaDataImport2_GetInterfaceImplProps( - meta, + metadata, tk_interface_impl, ptk_class.unwrap_or(0 as _), ptk_iface.unwrap_or(0 as _), @@ -403,7 +401,7 @@ pub mod imeta_data_import2 { } pub(crate) fn enum_methods( - meta: *mut c_void, + metadata: *mut IMetaDataImport2, ph_enum: *mut HCORENUM, tk_type_def: mdTypeDef, rg_methods: *mut mdMethodDef, @@ -413,7 +411,7 @@ pub mod imeta_data_import2 { unsafe { HRESULT( core_bindings::IMetaDataImport2_EnumMethods( - meta, + metadata, ph_enum, tk_type_def, rg_methods, @@ -425,7 +423,7 @@ pub mod imeta_data_import2 { } pub(crate) fn enum_properties( - meta: *mut c_void, + metadata: *mut IMetaDataImport2, ph_enum: *mut HCORENUM, tk_typ_def: mdTypeDef, rg_properties: *mut mdProperty, @@ -435,7 +433,7 @@ pub mod imeta_data_import2 { unsafe { HRESULT( core_bindings::IMetaDataImport2_EnumProperties( - meta, + metadata, ph_enum, tk_typ_def, rg_properties, @@ -447,7 +445,7 @@ pub mod imeta_data_import2 { } pub fn enum_events( - meta: *mut c_void, + metadata: *mut IMetaDataImport2, ph_enum: *mut HCORENUM, tk_typ_def: mdTypeDef, rg_events: *mut mdEvent, @@ -457,7 +455,7 @@ pub mod imeta_data_import2 { unsafe { HRESULT( core_bindings::IMetaDataImport2_EnumEvents( - meta, + metadata, ph_enum, tk_typ_def, rg_events, @@ -469,7 +467,7 @@ pub mod imeta_data_import2 { } pub(crate) fn get_event_props( - meta: *mut c_void, + metadata: *mut IMetaDataImport2, ev: mdEvent, p_class: Option<*mut mdTypeDef>, sz_event: Option, @@ -487,7 +485,7 @@ pub mod imeta_data_import2 { unsafe { HRESULT( core_bindings::IMetaDataImport2_GetEventProps( - meta, + metadata, ev, p_class.unwrap_or(0 as _), sz_event.unwrap_or(0 as _), @@ -508,7 +506,7 @@ pub mod imeta_data_import2 { pub(crate) fn find_field( - meta: *mut c_void, + metadata: *mut IMetaDataImport2, td: mdTypeDef, sz_name: Option, pv_sig_blob: Option, @@ -518,7 +516,7 @@ pub mod imeta_data_import2 { unsafe { HRESULT( core_bindings::IMetaDataImport2_FindField( - meta, + metadata, td, sz_name.unwrap_or(0 as _), pv_sig_blob.unwrap_or(0 as _), @@ -528,6 +526,94 @@ pub mod imeta_data_import2 { ) } } + + pub(crate) fn get_member_ref_props( + metadata: *mut IMetaDataImport2, + tk_member_ref: mdMemberRef, + ptk: Option<*mut mdToken>, + sz_member: Option, + cch_member: Option, + pch_member: Option<*mut ULONG>, + ppv_sig_blob: Option<*mut PCCOR_SIGNATURE>, + pcb_sig_blob: Option<*mut ULONG>, + ) -> HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_GetMemberRefProps( + metadata, + tk_member_ref, + ptk.unwrap_or(0 as _), + sz_member.unwrap_or(0 as _), + cch_member.unwrap_or_default(), + pch_member.unwrap_or(0 as _), + ppv_sig_blob.unwrap_or(0 as _), + pcb_sig_blob.unwrap_or(0 as _), + ) as u32) + } + } + + pub fn get_custom_attribute_props( + metadata: *mut IMetaDataImport2, + cv: mdCustomAttribute, + ptk_obj: Option<*mut mdToken>, + ptk_type: Option<*mut mdToken>, + pp_blob: Option<*mut *const BYTE>, + pcb_blob: Option<*mut ULONG>, + ) -> HRESULT { + HRESULT::from_win32( + unsafe { + core_bindings::IMetaDataImport2_GetCustomAttributeProps( + metadata, + cv, + ptk_obj.unwrap_or(0 as _), + ptk_type.unwrap_or(0 as _), + pp_blob.unwrap_or(0 as _), + pcb_blob.unwrap_or(0 as _), + ) + } as u32 + ) + } + + pub fn enum_custom_attributes( + metadata: *mut IMetaDataImport2, + ph_enum: Option<*mut HCORENUM>, + tk: Option, + tk_type: Option, + rg_custom_attributes: Option<*mut mdCustomAttribute>, + c_max: Option, + pc_custom_attributes: Option<*mut ULONG>, + ) -> HRESULT { + unsafe { + HRESULT::from_win32( + core_bindings::IMetaDataImport2_EnumCustomAttributes( + metadata, + ph_enum.unwrap_or(0 as _), + tk.unwrap_or_default(), + tk_type.unwrap_or_default(), + rg_custom_attributes.unwrap_or(0 as _), + c_max.unwrap_or_default(), + pc_custom_attributes.unwrap_or(0 as _), + ) as u32 + ) + } + } + + pub(crate) fn find_type_def_by_name( + metadata: *mut IMetaDataImport2, + sz_type_def: Option, + tk_enclosing_class: Option, + ptk_type_def: Option<*mut mdTypeDef>, + ) -> HRESULT { + unsafe { + HRESULT::from_win32( + core_bindings::IMetaDataImport2_FindTypeDefByName( + metadata, + sz_type_def.unwrap_or(0 as _), + tk_enclosing_class.unwrap_or(0 as _), + ptk_type_def.unwrap_or(0 as _), + ) as u32 + ) + } + } } pub mod iro_simple_meta_data_builder { @@ -666,8 +752,8 @@ pub mod helpers { use core_bindings::PCCOR_SIGNATURE; use windows::HSTRING; - pub(crate) fn get_type_name(meta: *mut c_void, md_token: mdToken, name: *mut libc::wchar_t, size: ULONG) -> ULONG { - unsafe { core_bindings::Helpers_Get_Type_Name(meta, md_token, name, size) } + pub(crate) fn get_type_name(metadata: *mut IMetaDataImport2, md_token: mdToken, name: *mut libc::wchar_t, size: ULONG) -> ULONG { + unsafe { core_bindings::Helpers_Get_Type_Name(metadata, md_token, name, size) } } pub(crate) fn is_td_public(value: DWORD) -> bool { diff --git a/core/src/metadata/declaration_factory.rs b/core/src/metadata/declaration_factory.rs index ac42009..bbf3a5d 100644 --- a/core/src/metadata/declaration_factory.rs +++ b/core/src/metadata/declaration_factory.rs @@ -19,7 +19,7 @@ impl DeclarationFactory { { CorTokenType::mdtTypeDef => Box::new(DelegateDeclaration::new(metadata, token)), CorTokenType::mdtTypeRef => { - let mut external_metadata = std::ptr::null_mut(); + let mut external_metadata = std::mem::MaybeUninit::uninit(); let mut external_delegate_token = mdTokenNil; let is_resolved = resolve_type_ref(metadata, token, &mut external_metadata, &mut external_delegate_token); debug_assert!(is_resolved); @@ -51,7 +51,7 @@ impl DeclarationFactory { Box::new(GenericDelegateInstanceDeclaration::new(metadata, open_generic_delegate_token, metadata, token)) } CorTokenType::mdtTypeRef => { - let mut external_metadata = std::ptr::null_mut(); + let mut external_metadata = std::mem::MaybeUninit::uninit(); let external_metadata_ptr = &mut external_metadata; let mut external_delegate_token = mdTokenNil; @@ -80,7 +80,7 @@ impl DeclarationFactory { ) } CorTokenType::mdtTypeRef => { - let mut external_metadata = std::ptr::null_mut(); + let mut external_metadata = std::mem::MaybeUninit::uninit(); let external_metadata_ptr = &mut external_metadata; let mut external_interface_token = mdTokenNil; @@ -126,7 +126,7 @@ impl DeclarationFactory { ) } CorTokenType::mdtTypeRef => { - let mut external_metadata = std::ptr::null_mut(); + let mut external_metadata = std::mem::MaybeUninit::uninit(); let external_metadata_ptr = &mut external_metadata; let mut external_delegate_token = mdTokenNil; diff --git a/core/src/metadata/declarations/base_class_declaration.rs b/core/src/metadata/declarations/base_class_declaration.rs index 65b3baa..4cc7a05 100644 --- a/core/src/metadata/declarations/base_class_declaration.rs +++ b/core/src/metadata/declarations/base_class_declaration.rs @@ -28,7 +28,7 @@ pub struct BaseClassDeclaration<'a> { impl<'a> BaseClassDeclaration<'a> { fn make_implemented_interfaces_declarations(metadata: *mut c_void, token: mdTypeDef) -> Vec>> { - let mut enumerator = std::ptr::null_mut(); + let mut enumerator = std::mem::MaybeUninit::uninit(); let enumerator_ptr = &mut enumerator; let mut count = 0; let mut tokens = [0; 1024]; @@ -62,7 +62,7 @@ impl<'a> BaseClassDeclaration<'a> { } fn make_method_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec> { - let mut enumerator = std::ptr::null_mut(); + let mut enumerator = std::mem::MaybeUninit::uninit(); let enumerator_ptr = &mut enumerator; let mut count = 0; let mut tokens = [0; 1024]; @@ -88,7 +88,7 @@ impl<'a> BaseClassDeclaration<'a> { } fn make_property_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec> { - let mut enumerator = std::ptr::null_mut(); + let mut enumerator = std::mem::MaybeUninit::uninit(); let enumerator_ptr = &mut enumerator; let mut count = 0; let mut tokens = [0; 1024]; @@ -113,7 +113,7 @@ impl<'a> BaseClassDeclaration<'a> { } fn make_event_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec> { - let mut enumerator = std::ptr::null_mut(); + let mut enumerator = std::mem::MaybeUninit::uninit(); let enumerator_ptr = &mut enumerator; let mut count = 0; let mut tokens = [0; 1024]; @@ -149,9 +149,8 @@ impl<'a> BaseClassDeclaration<'a> { } } -pub trait BaseClassDeclarationImpl: Any { - fn as_any(&self) -> &dyn Any; - +pub trait BaseClassDeclarationImpl { + fn base(&self) -> &TypeDeclaration; fn implemented_interfaces<'a>(&self) -> &Vec>; @@ -209,7 +208,7 @@ pub trait BaseClassDeclarationImpl: Any { fn find_methods_with_name<'b>(&self, name: &str) -> Vec> { debug_assert!(!name.is_empty()); - let mut enumerator = std::ptr::null_mut(); + let mut enumerator = std::mem::MaybeUninit::uninit(); let enumerator_ptr = &mut enumerator; let mut method_tokens: Vec = vec![0; 1024]; let mut methods_count = 0; @@ -229,15 +228,11 @@ pub trait BaseClassDeclarationImpl: Any { } impl<'a> BaseClassDeclarationImpl for BaseClassDeclaration<'a> { - fn as_any(&self) -> &dyn Any { - self - } - fn base(&self) -> &TypeDeclaration<'a> { &self.base } - fn implemented_interfaces(&self) -> &Vec>> { + fn implemented_interfaces(&self) -> &Vec>> { &self.implemented_interfaces } diff --git a/core/src/metadata/declarations/class_declaration.rs b/core/src/metadata/declarations/class_declaration.rs index ceffd20..b151219 100644 --- a/core/src/metadata/declarations/class_declaration.rs +++ b/core/src/metadata/declarations/class_declaration.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; use std::str::FromStr; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use crate::{ metadata::declarations::method_declaration::MethodDeclaration @@ -10,12 +10,12 @@ use crate::bindings::helpers::get_type_name; use crate::metadata::declaration_factory::DeclarationFactory; use crate::metadata::declarations::base_class_declaration::{BaseClassDeclaration, BaseClassDeclarationImpl}; use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; -use crate::metadata::declarations::interface_declaration::interface_declaration::InterfaceDeclaration; use crate::prelude::*; +use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; const DEFAULT_ATTRIBUTE:&'static str = "Windows.Foundation.Metadata.DefaultAttribute"; -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct ClassDeclaration<'a> { initializers: Vec>, default_interface: Option>, @@ -25,13 +25,13 @@ pub struct ClassDeclaration<'a> { impl<'a> ClassDeclaration<'a> { fn make_initializer_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec>{ - let mut enumerator = std::ptr::null_mut(); + let mut enumerator = std::mem::MaybeUninit::uninit(); let enumerator_ptr = &mut enumerator; let mut count = 0; - let mut tokens:Vec = vec![0;1024]; + let mut tokens = [0;1024]; - let name = OsString::from_str(COR_CTOR_METHOD_NAME).unwrap(); - let name = name.to_wide(); + let name = windows::HSTRING::from(COR_CTOR_METHOD_NAME); + let name = name.as_wide(); debug_assert!( imeta_data_import2::enum_methods_with_name( metadata, enumerator_ptr, token, name.as_ptr(), tokens.as_mut_ptr(), @@ -44,7 +44,8 @@ impl<'a> ClassDeclaration<'a> { imeta_data_import2::close_enum(metadata, enumerator); let mut result = Vec::new(); - for i in 0..count { + + for i in 0..count as usize { let method_token = tokens[i]; // TODO: Make a InstanceInitializerDeclaration and check this in it's isExported method @@ -69,10 +70,10 @@ impl<'a> ClassDeclaration<'a> { return result; } - fn make_default_interface(metadata: *mut c_void, token: mdTypeDef) -> Option> { - let mut interface_impl_tokens = vec![0_1024]; + fn make_default_interface(metadata: *mut c_void, token: mdTypeDef) -> Arc> { + let mut interface_impl_tokens = [0;1024]; let mut interface_impl_count = 0; - let mut interface_enumerator = std::ptr::null_mut(); + let mut interface_enumerator = std::mem::MaybeUninit::uninit(); let interface_enumerator_ptr = &mut interface_enumerator; debug_assert!( imeta_data_import2::enum_interface_impls( @@ -82,10 +83,11 @@ impl<'a> ClassDeclaration<'a> { ).is_ok() ); - debug_assert!(interface_impl_count < interface_impl_tokens.size()); + debug_assert!(interface_impl_count < interface_impl_tokens.len() as u32); imeta_data_import2::close_enum(metadata, interface_enumerator); - let attr = DEFAULT_ATTRIBUTE.to_wide(); - for i in 0..interface_impl_count { + let attr = windows::HSTRING::from(DEFAULT_ATTRIBUTE); + let attr = attr.as_wide(); + for i in 0..interface_impl_count as usize { let interface_impl_token = interface_impl_tokens[i]; let get_custom_attribute_result = imeta_data_import2::get_custom_attribute_by_name( metadata, interface_impl_token, Some(attr.as_ptr()), None, None @@ -124,11 +126,11 @@ impl<'a> ClassDeclaration<'a> { base.token, None, None,None,None, Some(&mut parent_token) - ) + ).is_ok() ); let mut name = [0_u16; MAX_IDENTIFIER_LENGTH]; let count = get_type_name(base.metadata, parent_token, name.as_mut_ptr(), name.len() as u32); - OsString::from_wide(name[..count]).into() + OsString::from_wide(&name[..count as usize]).to_string_lossy() } pub fn default_interface(&self) -> &InterfaceDeclaration{ diff --git a/core/src/metadata/declarations/declaration.rs b/core/src/metadata/declarations/declaration.rs index f31fd39..f7779e5 100644 --- a/core/src/metadata/declarations/declaration.rs +++ b/core/src/metadata/declarations/declaration.rs @@ -35,7 +35,8 @@ pub trait Declaration { fn kind(&self) -> DeclarationKind; - fn as_any(&self) -> &dyn Any { - self + fn as_any(value: &T) -> &dyn Any { + value as &dyn Any } + } diff --git a/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs b/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs index ea78885..83eb6cc 100644 --- a/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs +++ b/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs @@ -26,7 +26,7 @@ impl<'a> GenericDelegateDeclaration<'a> { pub fn number_of_generic_parameters(&self) -> usize { let mut count = 0; - let mut enumerator = std::ptr::null_mut(); + let mut enumerator = std::mem::MaybeUninit::uninit(); let enumerator_ptr = &mut enumerator; debug_assert!( diff --git a/core/src/metadata/declarations/interface_declaration/generic_interface_declaration.rs b/core/src/metadata/declarations/interface_declaration/generic_interface_declaration.rs index ee85458..9552a24 100644 --- a/core/src/metadata/declarations/interface_declaration/generic_interface_declaration.rs +++ b/core/src/metadata/declarations/interface_declaration/generic_interface_declaration.rs @@ -6,11 +6,11 @@ use crate::bindings::imeta_data_import2; use crate::metadata::declarations::base_class_declaration::BaseClassDeclarationImpl; use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; use crate::metadata::declarations::event_declaration::EventDeclaration; -use crate::metadata::declarations::interface_declaration::interface_declaration::InterfaceDeclaration; use crate::metadata::declarations::method_declaration::MethodDeclaration; use crate::metadata::declarations::property_declaration::PropertyDeclaration; use crate::metadata::declarations::type_declaration::TypeDeclaration; use crate::prelude::c_void; +use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; #[derive(Clone, Debug)] pub struct GenericInterfaceDeclaration<'a> { @@ -26,7 +26,7 @@ impl<'a> GenericInterfaceDeclaration<'a> { pub fn number_of_generic_parameters(&self) -> usize { let mut count = 0; - let mut enumerator = std::ptr::null_mut(); + let mut enumerator = std::mem::MaybeUninit::uninit(); let enumerator_ptr = &mut enumerator; let base = self.base.base.base(); debug_assert!( diff --git a/core/src/metadata/declarations/method_declaration.rs b/core/src/metadata/declarations/method_declaration.rs index b2161e8..e985564 100644 --- a/core/src/metadata/declarations/method_declaration.rs +++ b/core/src/metadata/declarations/method_declaration.rs @@ -28,7 +28,7 @@ impl<'a> MethodDeclaration <'a> { assert!(token != mdMethodDefNil); - let mut signature = std::ptr::null_mut(); + let mut signature = std::mem::MaybeUninit::uninit(); let mut signature_ptr = &mut signature; let mut signature_size: ULONG = 0; @@ -57,7 +57,7 @@ impl<'a> MethodDeclaration <'a> { let return_type = Signature::consume_type(signature as *const u8); let mut parameters: Vec = Vec::new(); - let mut parameter_enumerator = std::ptr::null_mut(); + let mut parameter_enumerator = std::mem::MaybeUninit::uninit(); let enumerator = &mut parameter_enumerator; let mut parameters_count: ULONG = 0; let mut parameter_tokens: Vec = vec![0; 1024]; diff --git a/core/src/metadata/declarations/namespace_declaration.rs b/core/src/metadata/declarations/namespace_declaration.rs index 09f3398..6b02ce6 100644 --- a/core/src/metadata/declarations/namespace_declaration.rs +++ b/core/src/metadata/declarations/namespace_declaration.rs @@ -99,7 +99,7 @@ impl <'a>NamespaceDeclaration <'a>{ Self { base: TypeDeclaration::new( DeclarationKind::Namespace, - std::ptr::null_mut(), + std::mem::MaybeUninit::uninit(), 0 ), children, diff --git a/core/src/metadata/declarations/struct_declaration.rs b/core/src/metadata/declarations/struct_declaration.rs index 136475d..3a01c14 100644 --- a/core/src/metadata/declarations/struct_declaration.rs +++ b/core/src/metadata/declarations/struct_declaration.rs @@ -45,7 +45,7 @@ impl<'a> StructDeclaration<'a> { } fn make_field_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec> { - let mut enumerator = std::ptr::null_mut(); + let mut enumerator = std::mem::MaybeUninit::uninit(); let mut count = 0; let mut tokens = [0; 1024]; let mut enumerator_ptr = &mut enumerator; diff --git a/core/src/metadata/declarations/struct_field_declaration.rs b/core/src/metadata/declarations/struct_field_declaration.rs index de37c37..86552fb 100644 --- a/core/src/metadata/declarations/struct_field_declaration.rs +++ b/core/src/metadata/declarations/struct_field_declaration.rs @@ -3,8 +3,9 @@ use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; use crate::metadata::declarations::field_declaration::FieldDeclaration; use crate::bindings::{imeta_data_import2, helpers}; use std::borrow::Cow; -use crate::metadata::declarations::type_declaration::TypeDeclaration; + +#[derive(Clone,Debug)] pub struct StructFieldDeclaration<'a> { base: FieldDeclaration<'a>, } diff --git a/core/src/metadata/declarations/type_declaration.rs b/core/src/metadata/declarations/type_declaration.rs index 2475793..531209a 100644 --- a/core/src/metadata/declarations/type_declaration.rs +++ b/core/src/metadata/declarations/type_declaration.rs @@ -6,7 +6,7 @@ use crate::{ enums, }, }; -use super::declaration::{Declaration, DeclarationKind}; +pub use super::declaration::{Declaration, DeclarationKind}; use std::marker; use std::ffi::{OsString}; use std::borrow::Cow; @@ -64,7 +64,7 @@ impl<'a> Declaration for TypeDeclaration<'a> { fn full_name<'b>(&self) -> Cow<'b, str> { let mut full_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; let length = helpers::get_type_name(self.metadata, self.token, full_name_data.as_mut_ptr(), full_name_data.len() as u32); - OsString::from_wide(&full_name_data[..length]).into() + OsString::from_wide(&full_name_data[..length as usize]).to_string_lossy() } fn kind(&self) -> DeclarationKind { diff --git a/core/src/metadata/declaring_interface_for_method.rs b/core/src/metadata/declaring_interface_for_method.rs new file mode 100644 index 0000000..0e41bbc --- /dev/null +++ b/core/src/metadata/declaring_interface_for_method.rs @@ -0,0 +1,158 @@ +use crate::prelude::*; +use crate::bindings::{enums, imeta_data_import2, helpers}; +use std::borrow::Cow; +use crate::metadata::com_helpers::get_string_value_from_blob; + +#[derive(Debug)] +pub struct DeclaringInterfaceForMethod {} + +impl DeclaringInterfaceForMethod { + pub fn get_method_containing_class_token(metadata: *mut IMetaDataImport2, method_token: mdMethodDef) -> u32 { + let mut class_token = mdTokenNil; + + match CorTokenType::from(enums::type_from_token(method_token)) { + CorTokenType::mdtMethodDef => { + debug_assert!( + imeta_data_import2::get_method_props( + metadata, method_token, Some(&mut class_token), None, + None, None, None, None, + None, None, None, + ).is_ok() + ); + } + CorTokenType::mdtMemberRef => { + debug_assert!( + imeta_data_import2::get_member_ref_props( + metadata, method_token, Some(&mut class_token), None, None, + None, None, None, + ).is_ok() + ); + } + _ => { + std::unreachable!() + } + } + + return class_token; + } + + pub fn get_custom_attribute_constructor_token(metadata: *mut IMetaDataImport2, custom_attribute: mdCustomAttribute) -> u32 { + let mut constructor_token = mdTokenNil; + debug_assert!( + imeta_data_import2::get_custom_attribute_props( + metadata, custom_attribute, None, Some(&mut constructor_token), + None, None, + ).is_ok() + ); + constructor_token + } + + pub fn get_custom_attribute_class_token(metadata: *mut IMetaDataImport2, custom_attribute: mdCustomAttribute) -> u32 { + DeclaringInterfaceForMethod::get_method_containing_class_token(metadata, DeclaringInterfaceForMethod::get_custom_attribute_constructor_token(metadata, custom_attribute)) + } + + pub fn get_method_signature<'a>(metadata: *mut IMetaDataImport2, token: mdMethodDef) -> Cow<'a, u8> { + let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; + let signature_ptr = &mut signature.as_mut_ptr(); + let mut signature_size = 0; + match CorTokenType::from(enums::type_from_token(token)) { + CorTokenType::mdtMethodDef => { + imeta_data_import2::get_method_props( + metadata, token, + None, None, None, None, + None, Some(signature_ptr as *mut *const u8), + Some(&mut signature_size), None, None, + ).is_ok() + } + CorTokenType::mdtMemberRef => { + imeta_data_import2::get_member_ref_props( + metadata, token, None, + None, None, None, Some(signature_ptr as *mut *const u8), + Some(&mut signature_size), + ).is_ok() + } + _ => { + std::unreachable!() + } + } + // todo clean up + let mut new_signature: [u8] = signature[..signature_size]; + let os = unsafe { new_signature.as_ptr().offset(1) }; + unsafe { std::slice::from_raw_parts(os, new_signature.len() - 1).into() } + } + + pub fn get_signature_argument_count(metadata: *mut IMetaDataImport2, signature: PCCOR_SIGNATURE) -> u32 { + helpers::cor_sig_uncompress_data(signature) + } + + pub fn get_method_argument_count(metadata: *mut IMetaDataImport2, token: mdToken) { + let signature = DeclaringInterfaceForMethod::get_method_signature(metadata, token).into_owned(); + DeclaringInterfaceForMethod::get_signature_argument_count(metadata, &signature); + } + + + pub fn get_custom_attributes_with_name(metadata: *mut IMetaDataImport2, token: mdTypeDef, attribute_name: *const wchar_t) { + // mdCustomAttribute + let mut attributes = [0;512]; + let mut attributes_count = 0; + let mut attributes_enumerator = std::mem::MaybeUninit::uninit(); + let attributes_enumerator_ptr = &mut attributes_enumerator; + + debug_assert!( + imeta_data_import2::enum_custom_attributes( + metadata, Some(attributesEnumerator_ptr), token, None, + Some(attributes.as_mut_ptr()), Some(attributes.len()), + Some(&mut attributesCount); + ).is_ok() + ); + debug_assert!( + attributes_count < attributes.len() -1 + ); + imeta_data_import2::close_enum( + metadata, attributes_enumerator + ); + + + let mut filtered_attributes = Vec::new(); + let new_attributes: [i32] = attributes[..attributes_count]; + for attribute in new_attributes.iter() { + let class_attribute_class_token = DeclaringInterfaceForMethod::get_custom_attribute_class_token(metadata, attribute); + let mut name = [0_u16; MAX_IDENTIFIER_LENGTH]; + let length = helpers::get_type_name(metadata, class_attribute_class_token, name.as_mut_ptr(), name.len() as u32); + let mut class_attribute_class_name:[u16] = name[..length]; + // TODO + if class_attribute_class_name.as_ptr() != attribute_name { + continue; + } + + filtered_attributes.push( + attribute + ); + + filtered_attributes.push_back(attribute); + } + filtered_attributes + } + + pub fn get_custom_attribute_type_argument(metadata: *mut IMetaDataImport2, token: mdCustomAttribute) { + let mut attribute_value = std::mem::MaybeUninit::uninit(); + let attribute_value_ptr = &mut attribute_value; + let mut attribute_value_size = 0; + debug_assert!(imeta_data_import2::get_custom_attribute_props( + metadata, token, + None, None, Some(attribute_value_ptr as *mut *const u8), Some(&mut attribute_value_size) + ).is_ok()); + + let type_name = get_string_value_from_blob( + metadata, attribute_value.as_ptr().offset(2) + ); + + + let mut typeToken = mdTokenNil; + debug_assert!(imeta_data_import2::find_type_def_by_name( + metadata, type_name_data, None, Some(&mut typeToken) + ).is_ok()) + return typeToken; + } + +} \ No newline at end of file diff --git a/core/src/metadata/generic_instance_id_builder.rs b/core/src/metadata/generic_instance_id_builder.rs index 478be41..21eae9c 100644 --- a/core/src/metadata/generic_instance_id_builder.rs +++ b/core/src/metadata/generic_instance_id_builder.rs @@ -1,5 +1,3 @@ - - use core_bindings::GUID; pub use crate::bindings::{iro_simple_meta_data_builder, rometadataresolution}; @@ -15,13 +13,14 @@ use crate::metadata::meta_data_reader::MetadataReader; use crate::metadata::signature::Signature; use crate::prelude::*; use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; +use std::any::Any; #[derive(Debug)] pub struct GenericInstanceIdBuilder {} impl GenericInstanceIdBuilder { extern "C" fn locator_impl(name: PCWSTR, builder: *mut IRoSimpleMetaDataBuilder) -> i32 { - let declaration = MetadataReader::find_by_name_w(name); + let declaration = MetadataReader::find_by_name_w(name); debug_assert!(declaration.is_some()); if let Some(declaration) = declaration { @@ -39,10 +38,10 @@ impl GenericInstanceIdBuilder { debug_assert!( iro_simple_meta_data_builder::set_runtime_class_simple_default( builder, name, full_name_w.as_ptr(), - &default_interface_id + &default_interface_id, ).is_ok() ); - return 0 + return 0; } DeclarationKind::Interface => { let mut interface_declaration = declaration @@ -51,9 +50,9 @@ impl GenericInstanceIdBuilder { .unwrap(); let interface_declaration_id = interface_declaration.id(); iro_simple_meta_data_builder::set_win_rt_interface( - builder,interface_declaration_id + builder, interface_declaration_id, ); - return 0 + return 0; } DeclarationKind::GenericInterface => { let mut generic_interface_declaration = declaration @@ -62,10 +61,10 @@ impl GenericInstanceIdBuilder { .unwrap(); debug_assert!( iro_simple_meta_data_builder::set_parameterized_interface( - builder, generic_interface_declaration.id(), generic_interface_declaration.number_of_generic_parameters() as u32 + builder, generic_interface_declaration.id(), generic_interface_declaration.number_of_generic_parameters() as u32, ).is_ok() ); - return 0 + return 0; } DeclarationKind::Enum => { let mut enum_declaration = declaration @@ -76,7 +75,7 @@ impl GenericInstanceIdBuilder { let full_name = windows::HSTRING::from(enum_declaration.full_name().to_owned().as_ref()); let full_name_w = full_name.as_wide(); let signature = Signature::to_string( - std::ptr::null() as _, type_.as_ptr() + std::ptr::null() as _, type_.as_ptr(), ); let signature = windows::HSTRING::from( signature.to_owned().as_ref() @@ -85,15 +84,15 @@ impl GenericInstanceIdBuilder { debug_assert!( iro_simple_meta_data_builder::set_enum( builder, full_name_w.as_ptr(), - signature_w.as_ptr() + signature_w.as_ptr(), ).is_ok() ); - return 0 + return 0; } DeclarationKind::Struct => { - + let mut declaration_any = declaration as &dyn Any; let mut struct_declaration = declaration - .as_any() + .downcast_ref::() .unwrap(); @@ -101,7 +100,7 @@ impl GenericInstanceIdBuilder { for field in struct_declaration.fields().iter() { let field_type = field.type_().to_owned(); let signature = Signature::to_string( - field.base().metadata, field_type.as_ptr() + field.base().metadata, field_type.as_ptr(), ); let signature = windows::HSTRING::from(signature.as_ref()); @@ -115,11 +114,11 @@ impl GenericInstanceIdBuilder { iro_simple_meta_data_builder::set_struct( builder, full_name_w.as_ptr(), struct_declaration.size() as u32, - field_names.as_ptr() + field_names.as_ptr(), ).is_ok() ); - return 0 + return 0; } DeclarationKind::Delegate => { let mut delegate_declaration = declaration @@ -130,10 +129,10 @@ impl GenericInstanceIdBuilder { debug_assert!( iro_simple_meta_data_builder::set_delegate( - builder, delegate_declaration.id() + builder, delegate_declaration.id(), ).is_ok() ); - return 0 + return 0; } DeclarationKind::GenericDelegate => { let mut generic_delegate_declaration = declaration @@ -142,10 +141,10 @@ impl GenericInstanceIdBuilder { .unwrap(); debug_assert!( iro_simple_meta_data_builder::set_parameterized_delegate( - builder, generic_delegate_declaration.id(), generic_delegate_declaration.number_of_generic_parameters() as u32 + builder, generic_delegate_declaration.id(), generic_delegate_declaration.number_of_generic_parameters() as u32, ).is_ok() ); - return 0 + return 0; } _ => { std::unreachable!() @@ -159,7 +158,7 @@ impl GenericInstanceIdBuilder { let mut declaration_full_name = declaration.full_name().into_owned(); let mut declaration_full_name = windows::HSTRING::from(declaration_full_name); let mut declaration_full_name = declaration_full_name.as_wide(); - let mut name_parts = [0_u16;MAX_IDENTIFIER_LENGTH]; + let mut name_parts = [0_u16; MAX_IDENTIFIER_LENGTH]; let mut name_parts_count = 0; let mut name_parts_w = &mut name_parts.as_ptr(); @@ -168,11 +167,10 @@ impl GenericInstanceIdBuilder { let mut guid = GUID::default(); debug_assert!( rometadataresolution::ro_get_parameterized_type_instance_iid( - name_parts_count, name_parts_w, Some(GenericInstanceIdBuilder::locator_impl), &mut guid, None + name_parts_count, name_parts_w, Some(GenericInstanceIdBuilder::locator_impl), &mut guid, None, ).is_ok() ); return guid; } - } \ No newline at end of file diff --git a/core/src/metadata/meta_data_reader.rs b/core/src/metadata/meta_data_reader.rs index a829631..699cafb 100644 --- a/core/src/metadata/meta_data_reader.rs +++ b/core/src/metadata/meta_data_reader.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use windows::HSTRING; @@ -9,10 +9,10 @@ use crate::metadata::declarations::delegate_declaration::DelegateDeclaration; use crate::metadata::declarations::delegate_declaration::generic_delegate_declaration::GenericDelegateDeclaration; use crate::metadata::declarations::enum_declaration::EnumDeclaration; use crate::metadata::declarations::interface_declaration::generic_interface_declaration::GenericInterfaceDeclaration; -use crate::metadata::declarations::interface_declaration::interface_declaration::InterfaceDeclaration; use crate::metadata::declarations::namespace_declaration::NamespaceDeclaration; use crate::metadata::declarations::struct_declaration::StructDeclaration; use crate::prelude::*; +use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; const WINDOWS: &str = "Windows"; const SYSTEM_ENUM: &str = "System.Enum"; @@ -23,22 +23,22 @@ const SYSTEM_MULTICASTDELEGATE: &str = "System.MulticastDelegate"; pub struct MetadataReader {} impl MetadataReader { - pub fn find_by_name_w(full_name: PCWSTR) -> Option> { + pub fn find_by_name_w(full_name: PCWSTR) -> Option>> { let mut count = 0; helpers::to_string_length(full_name, &mut count); let slice = unsafe { std::slice::from_raw_parts(full_name, count) }; let name = OsString::from_wide(slice).to_string_lossy(); MetadataReader::find_by_name(name.as_ref()) } - pub fn find_by_name(full_name: &str) -> Option> { + pub fn find_by_name(full_name: &str) -> Option>> { if full_name.is_empty() { return Some( Arc::new( - NamespaceDeclaration::new("") + Mutex::new(NamespaceDeclaration::new("")) ) ); } - let mut metadata = std::ptr::null_mut(); + let mut metadata = std::mem::MaybeUninit::uninit(); let meta = &mut metadata; let mut token = mdTokenNil; let mut full_name_hstring = HSTRING::from(full_name); @@ -49,7 +49,9 @@ impl MetadataReader { if get_metadata_file_result.is_err() { if get_metadata_file_result == windows::HRESULT::from_win32(RO_E_METADATA_NAME_IS_NAMESPACE as u32) { return Some( - Arc::new(NamespaceDeclaration::new(full_name)) + Arc::new( + Mutex::new(NamespaceDeclaration::new(full_name)) + ) ); } return None; @@ -92,7 +94,7 @@ impl MetadataReader { if parent_name_string == SYSTEM_ENUM { return Some( Arc::new( - EnumDeclaration::new(metadata, token) + Mutex::new(EnumDeclaration::new(metadata, token)) ) ); } @@ -100,7 +102,7 @@ impl MetadataReader { if parent_name_string == SYSTEM_VALUETYPE { return Some( Arc::new( - StructDeclaration::new(metadata, token) + Mutex::new(StructDeclaration::new(metadata, token)) ) ); } @@ -109,13 +111,13 @@ impl MetadataReader { return if full_name.contains("`") { Some( Arc::new( - GenericDelegateDeclaration::new(metadata, token) + Mutex::new(GenericDelegateDeclaration::new(metadata, token)) ) ) } else { Some( Arc::new( - DelegateDeclaration::new(metadata, token) + Mutex::new(DelegateDeclaration::new(metadata, token)) ) ) } @@ -123,7 +125,7 @@ impl MetadataReader { return Some( Arc::new( - ClassDeclaration::new(metadata, token) + Mutex::new(ClassDeclaration::new(metadata, token)) ) ); } @@ -132,13 +134,13 @@ impl MetadataReader { return if full_name.contains("`") { Some( Arc::new( - GenericInterfaceDeclaration::new(metadata, token) + Mutex::new(GenericInterfaceDeclaration::new(metadata, token)) ) ) } else { Some( Arc::new( - InterfaceDeclaration::new(metadata, token) + Mutex::new(InterfaceDeclaration::new(metadata, token)) ) ) }; diff --git a/core/src/metadata/mod.rs b/core/src/metadata/mod.rs index 3ded577..21c064e 100755 --- a/core/src/metadata/mod.rs +++ b/core/src/metadata/mod.rs @@ -4,3 +4,4 @@ pub mod signature; pub mod declaration_factory; pub mod generic_instance_id_builder; pub mod meta_data_reader; +pub mod declaring_interface_for_method; diff --git a/core/src/runtime/console.rs b/core/src/runtime/console.rs index 593358c..9623ae9 100755 --- a/core/src/runtime/console.rs +++ b/core/src/runtime/console.rs @@ -22,7 +22,7 @@ pub(crate) fn handle_console_log(scope: &mut v8::HandleScope, args: v8::Function let string = CString::new(value).unwrap(); let mut written = 0_u32; unsafe { - Console::WriteConsoleA(handle, string.as_ptr() as *const c_void, length, &mut written, std::ptr::null_mut()); + Console::WriteConsoleA(handle, string.as_ptr() as *const c_void, length, &mut written, std::ptr::null()); } } @@ -43,6 +43,6 @@ pub(crate) fn handle_console_dir(scope: &mut v8::HandleScope, args: v8::Function let string = CString::new(value).unwrap(); let mut written = 0_u32; unsafe { - Console::WriteConsoleA(handle, string.as_ptr() as *const c_void, length, &mut written, std::ptr::null_mut()); + Console::WriteConsoleA(handle, string.as_ptr() as *const c_void, length, &mut written, std::ptr::null()); } } \ No newline at end of file diff --git a/core/src/runtime/mod.rs b/core/src/runtime/mod.rs index 02863fa..9fe94c2 100755 --- a/core/src/runtime/mod.rs +++ b/core/src/runtime/mod.rs @@ -9,7 +9,6 @@ use std::os::raw::{c_char, c_uint, c_long}; use std::io::Read; use std::os::windows::prelude::*; use std::path::{Path, PathBuf}; -use crate::runtime::metadata::com_helpers::{get_type_name, IMetaDataImport2}; use windows::HSTRING; pub struct Runtime { @@ -193,98 +192,9 @@ impl Runtime { args: v8::FunctionCallbackArguments, mut retval: v8::ReturnValue) { println!("handle meta {:?}", args.get(0).to_rust_string_lossy(scope)); - let typeres_dll = CString::new("api-ms-win-ro-typeresolution-l1-1-0.dll").unwrap(); - let method = CString::new("RoGetMetaDataFile").unwrap(); - - let ro_get_meta_data_file: extern "stdcall" fn(windows::HSTRING, - *const c_void, - *const c_void, - *mut *mut c_void, - *mut u32 - ) -> windows::HRESULT; - - - - let proc = unsafe { - bindings::Windows::Win32::System::SystemServices::GetProcAddress( - bindings::Windows::Win32::System::SystemServices::LoadLibraryA( - "api-ms-win-ro-typeresolution-l1-1-0.dll" - ), - "RoGetMetaDataFile" - ) - }; - - ro_get_meta_data_file = unsafe { std::mem::transmute(proc) }; - - println!("RoGetMetaDataFile Address is {}", ro_get_meta_data_file as i64); let class_name = args.get(0).to_rust_string_lossy(scope); - let mut metadata = std::ptr::null_mut() as *mut c_void; - let mut token = 0_u32; - let mut metadata_ptr: *mut *mut c_void = &mut metadata; - // let result = ro_get_meta_data_file( - // class_name.into(), - // std::ptr::null(), - // std::ptr::null(), - // metadata, - // &mut token - // ); - - let result = unsafe { - Rometadataresolution_RoGetMetaDataFile( - class_name.into(), - std::ptr::null(), - std::ptr::null(), - metadata_ptr, - &mut token - ) - }; - - - let COR_CTOR_METHOD_NAME =".ctor"; - - - println!("metadata is {:?}", metadata); - - println!("token is {:?}", token); - println!("result is {:?}", result); - - - - - - let mut md: *mut IMetaDataImport2 = unsafe {std::mem::transmute(metadata)}; - - unsafe { - let mut name = vec![0_u16;MAX_IDENTIFIER_LENGTH]; - let length = Helpers_Get_Type_Name(md as *const c_void, token, name.as_mut_ptr(), name.len()); - name.resize(length as usize, 0); - let name = OsString::from_wide(name.as_slice()); - println!("nameaa {:?}", name); - println!("val {:?}", name.to_string_lossy()); - } - // let mut md = unsafe { &mut *md }; - - let mut parent_token = 0_u32; - let mut string = String::new(); - let mut name_length = 0; - - unsafe { - // IMetaDataImport2_EnumInterfaceImpls(md as _, token); - // IMetaDataImport2_GetTypeDefPropsNameSize(md as _, token, &mut name_length); - } - - println!("name_length {}", name_length); - - // unsafe { IMetaDataImport2_GetTypeDefProps(md as _, token, string.as_mut_ptr() as *mut c_void, string.len() as i64, &mut name_length, 0 as _, &mut parent_token); } - - // md.GetTypeDefProps(token, &mut string, &mut name_length, 0, &mut parent_token); - - println!("parent token {:?}", parent_token); - - let type_name = get_type_name(metadata as *mut c_void, parent_token); - println!("typename is {:?}", type_name); } } From ddf56004b41ccbd2b2dc26e45f5b67ac0ac42b86 Mon Sep 17 00:00:00 2001 From: Osei Fortune Date: Fri, 11 Jun 2021 11:35:03 -0400 Subject: [PATCH 08/11] updates --- core-bindings/src/bindings.cpp | 8 + core/src/bindings.rs | 121 ++++- core/src/metadata/com_helpers.rs | 14 +- .../declarations/base_class_declaration.rs | 6 +- .../declarations/interface_declaration/mod.rs | 4 +- .../declarations/method_declaration.rs | 3 + .../declarations/namespace_declaration.rs | 5 +- .../metadata/declarations/type_declaration.rs | 6 +- .../declaring_interface_for_method.rs | 512 ++++++++++++++++-- 9 files changed, 615 insertions(+), 64 deletions(-) diff --git a/core-bindings/src/bindings.cpp b/core-bindings/src/bindings.cpp index 9b35a8b..8443b59 100644 --- a/core-bindings/src/bindings.cpp +++ b/core-bindings/src/bindings.cpp @@ -374,6 +374,14 @@ extern "C" HRESULT IMetaDataImport2_FindTypeDefByName(IMetaDataImport2 * metadat return metadata->FindTypeDefByName(szTypeDef, tkEnclosingClass, ptkTypeDef); } +extern "C" HRESULT IMetaDataImport2_EnumMethodImpls(IMetaDataImport2 * metadata, HCORENUM * phEnum, + mdTypeDef tkTypeDef, + mdToken rMethodBody[], + mdToken rMethodDecl[], + ULONG cMax, + ULONG * pcTokens) { + return metadata->EnumMethodImpls(phEnum, tkTypeDef, rMethodBody, rMethodDecl, cMax, pcTokens); +} diff --git a/core/src/bindings.rs b/core/src/bindings.rs index e201f4f..047d80b 100644 --- a/core/src/bindings.rs +++ b/core/src/bindings.rs @@ -1,25 +1,72 @@ use crate::prelude::*; +use windows::Abi; -pub(crate) fn ro_resolve_namespace(name: HSTRING, - windows_meta_data_dir: Option, +pub(crate) fn ro_resolve_namespace(name: &windows::HSTRING, + windows_meta_data_dir: Option<&windows::HSTRING>, package_graph_dirs_count: DWORD, - package_graph_dirs: Option<*const HSTRING>, - meta_data_file_paths_count: Option<*mut DWORD>, - meta_data_file_paths: Option<*mut *mut HSTRING>, - sub_namespaces_count: *mut DWORD, - sub_namespaces: Option<*mut *mut HSTRING>, + package_graph_dirs: Option<&windows::HSTRING>, + meta_data_file_paths_count: Option<&mut DWORD>, + meta_data_file_paths: Option<&mut windows::HSTRING>, + sub_namespaces_count: &mut DWORD, + sub_namespaces: Option<&mut windows::HSTRING>, ) -> HRESULT { unsafe { + let name = name.abi() as HSTRING; + let windows_meta_data_dir = match windows_meta_data_dir { + None => { + 0 as _ + } + Some(windows_meta_data_dir) => { + windows_meta_data_dir.abi() + } + } as HSTRING; + let mut package_graph_dirs = match package_graph_dirs { + None => { + 0 as _ + } + Some(package_graph_dirs) => { + package_graph_dirs.abi() + } + }; + + let package_graph_dirs: *const *mut HSTRING__ = &mut package_graph_dirs as _; + let mut meta_data_file_paths = match meta_data_file_paths { + None => { + 0 as _ + } + Some(meta_data_file_paths) => { + meta_data_file_paths.abi() + } + }; + + let mut meta_data_file_paths = &mut meta_data_file_paths; + let meta_data_file_paths: *mut *mut HSTRING = &mut meta_data_file_paths as _; + + + let mut sub_namespaces = match sub_namespaces { + None => { + 0 as _ + } + Some(sub_namespaces) => { + sub_namespaces.abi() + } + }; + + let mut sub_namespaces = &mut sub_namespaces; + let sub_namespaces: *mut *mut HSTRING = &mut sub_namespaces as _; + core_bindings::RoResolveNamespace( - name, windows_meta_data_dir.unwrap_or(0 as _), package_graph_dirs_count, package_graph_dirs.unwrap_or(0 as _), meta_data_file_paths_count.unwrap_or(0 as _), meta_data_file_paths.unwrap_or(0 as _), sub_namespaces_count, sub_namespaces.unwrap_or(0 as _), + name, windows_meta_data_dir, package_graph_dirs_count, + package_graph_dirs, meta_data_file_paths_count.unwrap_or(0 as _), + meta_data_file_paths, sub_namespaces_count, sub_namespaces, ) } } pub mod rometadataresolution { use crate::prelude::*; - use windows::{HRESULT, HSTRING}; + use windows::{HRESULT, HSTRING, Abi}; pub(crate) fn ro_get_meta_data_file( name: &mut windows::HSTRING, meta_data_dispenser: Option<*mut c_void>, meta_data_file_path: Option<*mut c_void>, meta_data_import: Option<*mut *mut c_void>, type_def_token: Option<*mut u32>, @@ -32,16 +79,18 @@ pub mod rometadataresolution { } pub(crate) fn ro_parse_type_name( - mut type_name: HSTRING, - parts_count: *mut DWORD, - type_name_parts: *mut *mut HSTRING, + type_name: &mut windows::HSTRING, + parts_count: &mut DWORD, + type_name_parts: &mut windows::HSTRING, ) -> HRESULT { + let type_name = type_name.abi() as _; + let type_name_parts = type_name_parts.abi() as _; unsafe { HRESULT( core_bindings::Rometadataresolution_RoParseTypeName( - std::mem::transmute(&mut type_name), + type_name, parts_count, - std::mem::transmute(type_name_parts), + type_name_parts, ) as u32 ) } @@ -273,11 +322,11 @@ pub mod imeta_data_import2 { td: mdTypeDef, sz_name: LPCWSTR, pv_sig_blob: Option, - cb_sig_blob: ULONG, - pmb: *mut mdMethodDef) -> windows::HRESULT { + cb_sig_blob: Option, + pmb: Option<*mut mdMethodDef>) -> windows::HRESULT { unsafe { HRESULT( - IMetaDataImport2_FindMethod(metadata, td, sz_name, pv_sig_blob.unwrap_or(0 as _), cb_sig_blob, pmb) as u32 + IMetaDataImport2_FindMethod(metadata, td, sz_name, pv_sig_blob.unwrap_or(0 as _), cb_sig_blob.unwrap_or_default(), pmb.unwrap_or(0 as _)) as u32 ) } } @@ -610,7 +659,43 @@ pub mod imeta_data_import2 { sz_type_def.unwrap_or(0 as _), tk_enclosing_class.unwrap_or(0 as _), ptk_type_def.unwrap_or(0 as _), - ) as u32 + ) as u32 + ) + } + } + + pub fn enum_method_impls( + metadata: *mut IMetaDataImport2, + ph_enum: *mut HCORENUM, + tk_type_def: Option, + r_method_body: Option<&mut [mdToken]>, + r_method_decl: Option<&mut [mdToken]>, + c_max: Option, + pc_tokens: Option<&mut ULONG>, + ) -> HRESULT { + let r_method_body = if let Some(r_method_body) = r_method_body { + r_method_body.as_mut_ptr() + } else { + 0 as _ + }; + + let r_method_decl = if let Some(r_method_decl) = r_method_decl { + r_method_decl.as_mut_ptr() + } else { + 0 as _ + }; + + unsafe { + HRESULT::from_win32( + core_bindings::IMetaDataImport2_EnumMethodImpls( + metadata, + ph_enum, + tk_type_def.unwrap_or_default(), + r_method_body, + r_method_decl, + c_max.unwrap_or_default(), + pc_tokens.unwrap_or(0 as _), + ) as u32 ) } } diff --git a/core/src/metadata/com_helpers.rs b/core/src/metadata/com_helpers.rs index b4200bb..a7852d1 100755 --- a/core/src/metadata/com_helpers.rs +++ b/core/src/metadata/com_helpers.rs @@ -3,9 +3,15 @@ use crate::bindings::{helpers, imeta_data_import2, enums, rometadataresolution}; use std::borrow::Cow; -const GUID_ATTRIBUTE: &'static str = "Windows.Foundation.Metadata.GuidAttribute"; +const GUID_ATTRIBUTE: &str = "Windows.Foundation.Metadata.GuidAttribute"; -pub fn get_string_value_from_blob<'a>(metadata: *mut c_void, signature: PCCOR_SIGNATURE) -> Cow<'a, str> { +pub const SYSTEM_TYPE: &str = "System.Type"; +pub const STATIC_ATTRIBUTE: &str = "Windows.Foundation.Metadata.StaticAttribute"; +pub const ACTIVATABLE_ATTRIBUTE: &str = "Windows.Foundation.Metadata.ActivatableAttribute"; +pub const COMPOSABLE_ATTRIBUTE: &str = "Windows.Foundation.Metadata.ComposableAttribute"; + + +pub fn get_string_value_from_blob<'a>(metadata: *mut IMetaDataImport2, signature: PCCOR_SIGNATURE) -> Cow<'a, str> { debug_assert!(!metadata.is_null()); debug_assert!(!signature.is_null()); @@ -44,7 +50,7 @@ pub fn get_unary_custom_attribute_string_value<'a>(metadata: *mut c_void, token: } -pub fn resolve_type_ref(metadata: *mut c_void, token: mdTypeRef, external_metadata: *mut *mut c_void, external_token: *mut mdTypeDef) -> bool { +pub fn resolve_type_ref(metadata: *mut IMetaDataImport2, token: mdTypeRef, external_metadata: *mut *mut c_void, external_token: *mut mdTypeDef) -> bool { debug_assert!(!metadata.is_null()); debug_assert!(enums::type_from_token(token) == CorTokenType::mdtTypeRef as u32); debug_assert!(!external_metadata.is_null()); @@ -84,7 +90,7 @@ pub fn get_guid_attribute_value(metadata: *mut c_void, token: mdToken) -> GUID { guid } -pub fn get_type_name<'a>(metadata: *mut c_void, token: mdToken) -> Cow<'a, str> { +pub fn get_type_name<'a>(metadata: *mut IMetaDataImport2, token: mdToken) -> Cow<'a, str> { debug_assert!(!metadata.is_null()); debug_assert!(token != mdTokenNil); diff --git a/core/src/metadata/declarations/base_class_declaration.rs b/core/src/metadata/declarations/base_class_declaration.rs index 4cc7a05..afd5e7d 100644 --- a/core/src/metadata/declarations/base_class_declaration.rs +++ b/core/src/metadata/declarations/base_class_declaration.rs @@ -27,8 +27,8 @@ pub struct BaseClassDeclaration<'a> { } impl<'a> BaseClassDeclaration<'a> { - fn make_implemented_interfaces_declarations(metadata: *mut c_void, token: mdTypeDef) -> Vec>> { - let mut enumerator = std::mem::MaybeUninit::uninit(); + fn make_implemented_interfaces_declarations(metadata: *mut IMetaDataImport2, token: mdTypeDef) -> Vec>> { + let mut enumerator = std::ptr::null_mut(); let enumerator_ptr = &mut enumerator; let mut count = 0; let mut tokens = [0; 1024]; @@ -138,7 +138,7 @@ impl<'a> BaseClassDeclaration<'a> { result } - pub fn new(kind: DeclarationKind, metadata: *mut c_void, token: mdTypeDef) -> Self { + pub fn new(kind: DeclarationKind, metadata: *mut IMetaDataImport2, token: mdTypeDef) -> Self { Self { base: TypeDeclaration::new(kind, metadata, token), implemented_interfaces: BaseClassDeclaration::make_implemented_interfaces_declarations(metadata, token), diff --git a/core/src/metadata/declarations/interface_declaration/mod.rs b/core/src/metadata/declarations/interface_declaration/mod.rs index 6a0401d..3663fdc 100644 --- a/core/src/metadata/declarations/interface_declaration/mod.rs +++ b/core/src/metadata/declarations/interface_declaration/mod.rs @@ -23,13 +23,13 @@ pub struct InterfaceDeclaration<'a> { } impl<'a> InterfaceDeclaration<'a> { - pub fn new(metadata: *mut c_void, token: mdToken) -> Self { + pub fn new(metadata: *mut IMetaDataImport2, token: mdToken) -> Self { Self::new_with_kind( DeclarationKind::Interface, metadata, token, ) } - pub fn new_with_kind(kind: DeclarationKind, metadata: *mut c_void, token: mdToken) -> Self { + pub fn new_with_kind(kind: DeclarationKind, metadata: *mut IMetaDataImport2, token: mdToken) -> Self { Self { base: BaseClassDeclaration::new( kind, metadata, token, diff --git a/core/src/metadata/declarations/method_declaration.rs b/core/src/metadata/declarations/method_declaration.rs index e985564..07b7488 100644 --- a/core/src/metadata/declarations/method_declaration.rs +++ b/core/src/metadata/declarations/method_declaration.rs @@ -22,6 +22,9 @@ const OVERLOAD_ATTRIBUTE: &str = "Windows.Foundation.Metadata.OverloadAttribute" const DEFAULT_OVERLOAD_ATTRIBUTE: &str ="Windows.Foundation.Metadata.DefaultOverloadAttribute"; impl<'a> MethodDeclaration <'a> { + pub fn base (&self) -> &TypeDeclaration<'a> { + &self.base + } pub fn new(metadata: *mut c_void, token: mdMethodDef) -> Self { debug_assert!(!metadata.is_null()); debug_assert!(enums::type_from_token(token) == CorTokenType::mdtMethodDef as u32); diff --git a/core/src/metadata/declarations/namespace_declaration.rs b/core/src/metadata/declarations/namespace_declaration.rs index 6b02ce6..9f3e84f 100644 --- a/core/src/metadata/declarations/namespace_declaration.rs +++ b/core/src/metadata/declarations/namespace_declaration.rs @@ -42,12 +42,11 @@ impl <'a>NamespaceDeclaration <'a>{ let mut namespaces_count = 0; + let mut full_name_w = windows::HSTRING::from(full_name); // Grab size unsafe { ro_resolve_namespace( - std::mem::transmute( - windows::HSTRING::from(full_name) - ), + &mut full_name_w, None, 0, None, diff --git a/core/src/metadata/declarations/type_declaration.rs b/core/src/metadata/declarations/type_declaration.rs index 531209a..39c4d75 100644 --- a/core/src/metadata/declarations/type_declaration.rs +++ b/core/src/metadata/declarations/type_declaration.rs @@ -14,9 +14,9 @@ use std::borrow::Cow; #[derive(Clone, Debug)] pub struct TypeDeclaration<'a> { pub kind: DeclarationKind, - pub metadata: *mut c_void, + pub metadata: *mut IMetaDataImport2, pub token: mdTypeDef, - _marker: marker::PhantomData<&'a *const c_void>, + _marker: marker::PhantomData<&'a ()>, } @@ -73,7 +73,7 @@ impl<'a> Declaration for TypeDeclaration<'a> { } impl<'a> TypeDeclaration<'a> { - pub fn new(kind: DeclarationKind, metadata: *mut c_void, token: mdTypeDef) -> Self { + pub fn new(kind: DeclarationKind, metadata: *mut IMetaDataImport2, token: mdTypeDef) -> Self { let value = Self { kind, metadata, diff --git a/core/src/metadata/declaring_interface_for_method.rs b/core/src/metadata/declaring_interface_for_method.rs index 0e41bbc..47554dd 100644 --- a/core/src/metadata/declaring_interface_for_method.rs +++ b/core/src/metadata/declaring_interface_for_method.rs @@ -1,7 +1,12 @@ use crate::prelude::*; use crate::bindings::{enums, imeta_data_import2, helpers}; use std::borrow::Cow; -use crate::metadata::com_helpers::get_string_value_from_blob; +use crate::metadata::com_helpers::{get_string_value_from_blob, get_type_name, SYSTEM_TYPE, COMPOSABLE_ATTRIBUTE, ACTIVATABLE_ATTRIBUTE, STATIC_ATTRIBUTE, resolve_type_ref}; +use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; +use crate::metadata::declarations::interface_declaration::generic_interface_instance_declaration::GenericInterfaceInstanceDeclaration; +use crate::metadata::declarations::base_class_declaration::BaseClassDeclarationImpl; +use std::sync::{Arc, Mutex}; +use crate::metadata::declarations::method_declaration::MethodDeclaration; #[derive(Debug)] pub struct DeclaringInterfaceForMethod {} @@ -51,7 +56,7 @@ impl DeclaringInterfaceForMethod { DeclaringInterfaceForMethod::get_method_containing_class_token(metadata, DeclaringInterfaceForMethod::get_custom_attribute_constructor_token(metadata, custom_attribute)) } - pub fn get_method_signature<'a>(metadata: *mut IMetaDataImport2, token: mdMethodDef) -> Cow<'a, u8> { + pub fn get_method_signature<'a>(metadata: *mut IMetaDataImport2, token: mdMethodDef) -> Cow<'a, [u8]> { let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; let signature_ptr = &mut signature.as_mut_ptr(); let mut signature_size = 0; @@ -81,47 +86,47 @@ impl DeclaringInterfaceForMethod { unsafe { std::slice::from_raw_parts(os, new_signature.len() - 1).into() } } - pub fn get_signature_argument_count(metadata: *mut IMetaDataImport2, signature: PCCOR_SIGNATURE) -> u32 { - helpers::cor_sig_uncompress_data(signature) + pub fn get_signature_argument_count(metadata: *mut IMetaDataImport2, signature: Cow<[u8]>) -> u32 { + helpers::cor_sig_uncompress_data(signature.as_ptr()) } - pub fn get_method_argument_count(metadata: *mut IMetaDataImport2, token: mdToken) { - let signature = DeclaringInterfaceForMethod::get_method_signature(metadata, token).into_owned(); - DeclaringInterfaceForMethod::get_signature_argument_count(metadata, &signature); + pub fn get_method_argument_count(metadata: *mut IMetaDataImport2, token: mdToken) -> u32 { + let signature = DeclaringInterfaceForMethod::get_method_signature(metadata, token); + DeclaringInterfaceForMethod::get_signature_argument_count(metadata, signature) } - pub fn get_custom_attributes_with_name(metadata: *mut IMetaDataImport2, token: mdTypeDef, attribute_name: *const wchar_t) { + pub fn get_custom_attributes_with_name(metadata: *mut IMetaDataImport2, token: mdTypeDef, attribute_name: &str) -> Vec { // mdCustomAttribute - let mut attributes = [0;512]; - let mut attributes_count = 0; - let mut attributes_enumerator = std::mem::MaybeUninit::uninit(); - let attributes_enumerator_ptr = &mut attributes_enumerator; + let mut attributes = [0; 512]; + let mut attributes_count = 0; + let mut attributes_enumerator = std::ptr::null_mut(); + let attributes_enumerator_ptr = &mut attributes_enumerator; debug_assert!( imeta_data_import2::enum_custom_attributes( - metadata, Some(attributesEnumerator_ptr), token, None, - Some(attributes.as_mut_ptr()), Some(attributes.len()), - Some(&mut attributesCount); - ).is_ok() + metadata, Some(attributes_enumerator_ptr), Some(token), None, + Some(attributes.as_mut_ptr()), Some(attributes.len() as u32), + Some(&mut attributes_count), + ).is_ok() ); debug_assert!( - attributes_count < attributes.len() -1 + attributes_count < (attributes.len() - 1) as u32 ); imeta_data_import2::close_enum( - metadata, attributes_enumerator + metadata, attributes_enumerator, ); - let mut filtered_attributes = Vec::new(); - let new_attributes: [i32] = attributes[..attributes_count]; + let mut filtered_attributes: Vec = Vec::new(); + let new_attributes: [u32] = attributes[..attributes_count]; for attribute in new_attributes.iter() { let class_attribute_class_token = DeclaringInterfaceForMethod::get_custom_attribute_class_token(metadata, attribute); let mut name = [0_u16; MAX_IDENTIFIER_LENGTH]; let length = helpers::get_type_name(metadata, class_attribute_class_token, name.as_mut_ptr(), name.len() as u32); - let mut class_attribute_class_name:[u16] = name[..length]; + let mut class_attribute_class_name = windows::HSTRING::from_wide(name[..length]); // TODO - if class_attribute_class_name.as_ptr() != attribute_name { + if class_attribute_class_name != attribute_name { continue; } @@ -134,25 +139,470 @@ impl DeclaringInterfaceForMethod { filtered_attributes } - pub fn get_custom_attribute_type_argument(metadata: *mut IMetaDataImport2, token: mdCustomAttribute) { - let mut attribute_value = std::mem::MaybeUninit::uninit(); + pub fn get_custom_attribute_type_argument(metadata: *mut IMetaDataImport2, token: mdCustomAttribute) -> u32 { + let mut attribute_value = std::mem::MaybeUninit::uninit(); let attribute_value_ptr = &mut attribute_value; - let mut attribute_value_size = 0; + let mut attribute_value_size = 0; debug_assert!(imeta_data_import2::get_custom_attribute_props( metadata, token, - None, None, Some(attribute_value_ptr as *mut *const u8), Some(&mut attribute_value_size) + None, None, Some(attribute_value_ptr as *mut *const u8), Some(&mut attribute_value_size), ).is_ok()); let type_name = get_string_value_from_blob( - metadata, attribute_value.as_ptr().offset(2) + metadata, unsafe { attribute_value.as_ptr().offset(2) }, ); + let type_name_data = windows::HSTRING::from(type_name); + let type_name_data = type_name_data.as_wide(); - let mut typeToken = mdTokenNil; + let mut type_token = mdTokenNil; debug_assert!(imeta_data_import2::find_type_def_by_name( - metadata, type_name_data, None, Some(&mut typeToken) - ).is_ok()) - return typeToken; + metadata, Some(type_name_data.as_ptr()), None, Some(&mut type_token), + ).is_ok()); + return type_token; + } + + + pub fn get_class_methods<'a>(metadata: *mut IMetaDataImport2, token: mdTypeDef) -> Cow<'a, [u32]> { + let mut methods = [0; 1024]; + let mut methods_count = 0; + let mut methods_enumerator = std::ptr::null_mut(); + let methods_enumerator_ptr = &mut methods_enumerator; + debug_assert!( + imeta_data_import2::enum_methods( + metadata, methods_enumerator_ptr, token, methods.as_mut_ptr(), + methods.len() as u32, &mut methods_count, + ).is_ok() + ); + debug_assert!( + methods_count < (methods.len() - 1) as u32 + ); + imeta_data_import2::close_enum( + metadata, methods_enumerator, + ); + + methods[..methods_count] + } + + + pub fn has_method_first_type_argument(metadata: *mut IMetaDataImport2, token: mdToken) -> bool { + let mut signature = DeclaringInterfaceForMethod::get_method_signature( + metadata, token, + ); + let argument_count = helpers::cor_sig_uncompress_data(signature.as_ptr()); + + if argument_count == 0 { + return false; + } + + let return_type = helpers::cor_sig_uncompress_element_type(signature.as_ptr()); + + debug_assert!( + return_type == crate::enums::CorElementType::ElementTypeVoid + ); + + let first_argument = helpers::cor_sig_uncompress_element_type(signature.as_ptr()); + + + if first_argument == crate::enums::CorElementType::ElementTypeClass { + return false; + } + + let first_argument_token = helpers::cor_sig_uncompress_token(signature.as_ptr()); + let first_argument_type_name = get_type_name( + metadata, first_argument_token, + ); + + if first_argument_type_name != SYSTEM_TYPE { + return false; + } + + return true; } + + pub fn declaring_interface_for_initializer<'a>(metadata: *mut IMetaDataImport2, method_token: mdMethodDef, out_index: &mut usize) -> Option> { + // InterfaceDeclaration + let method_argument_count = DeclaringInterfaceForMethod::get_method_argument_count(metadata, method_token); + + let class_token = DeclaringInterfaceForMethod::get_method_containing_class_token(metadata, method_token); + + debug_assert!( + CorTokenType::from(enums::type_from_token(class_token)) == crate::enums::CorTokenType::mdtTypeDef + ); + + let composable_attributes = DeclaringInterfaceForMethod::get_custom_attributes_with_name( + metadata, class_token, COMPOSABLE_ATTRIBUTE, + ); + + for attributeToken in composable_attributes.iter() { + let factory_token = DeclaringInterfaceForMethod::get_custom_attribute_type_argument( + metadata, attributeToken, + ); + + let factory_methods = DeclaringInterfaceForMethod::get_class_methods( + metadata, attributeToken, + ); + + for (i, factoryMethod) in factory_methods.iter().enumerate() { + let factory_method_arguments_count = DeclaringInterfaceForMethod::get_method_argument_count(metadata, factoryMethod); + if factory_method_arguments_count - 2 != method_argument_count { + continue; + } + + *out_index = i; + return Some(InterfaceDeclaration::new(metadata, factory_token)); + } + } + + if method_argument_count == 0 { + *out_index = usize::MAX; + return None; + } + + + let mut activatable_attributes = DeclaringInterfaceForMethod::get_custom_attributes_with_name( + metadata, class_token, ACTIVATABLE_ATTRIBUTE, + ); + for attributeToken in activatable_attributes.iter() { + let attribute_constructor_token = DeclaringInterfaceForMethod::get_custom_attribute_constructor_token( + metadata, attributeToken, + ); + + if !DeclaringInterfaceForMethod::has_method_first_type_argument(metadata, attribute_constructor_token) { + continue; + } + + let factory_token = DeclaringInterfaceForMethod::get_custom_attribute_type_argument(metadata, attributeToken); + + + let factory_methods = DeclaringInterfaceForMethod::get_class_methods( + metadata, factory_token, + ); + + for (i, factory_method) in factory_methods.iter().enumerate() { + let factory_method_arguments_count = DeclaringInterfaceForMethod::get_method_argument_count( + metadata, factory_method, + ); + + if factory_method_arguments_count != method_argument_count { + continue; + } + + *out_index = i; + return Some(InterfaceDeclaration::new(metadata, factory_token)); + } + } + + // return Option ? + std::unreachable!(); + } + + + pub fn declaring_interface_for_static_method<'a>(metadata: *mut IMetaDataImport2, method_token: mdMethodDef, out_index: &mut usize) -> Option> { + let method_signature = DeclaringInterfaceForMethod::get_method_signature( + metadata, method_token, + ); + let class_token = DeclaringInterfaceForMethod::get_method_containing_class_token( + metadata, method_token, + ); + debug_assert!( + CorTokenType::from(enums::type_from_token(class_token)) == CorTokenType::mdtTypeDef + ); + + let static_attributes = DeclaringInterfaceForMethod::get_custom_attributes_with_name( + metadata, class_token, STATIC_ATTRIBUTE, + ); + + for attributeToken in static_attributes.iter() { + let statics_token = DeclaringInterfaceForMethod::get_custom_attribute_type_argument( + metadata, attributeToken, + ); + + let static_methods = DeclaringInterfaceForMethod::get_class_methods( + metadata, statics_token, + ); + + for (i, staticMethod) in static_methods.iter().enumerate() { + let mut static_signature = [0_u8; MAX_IDENTIFIER_LENGTH]; + let static_signature_ptr = &mut static_signature.as_mut_ptr(); + let mut static_signature_size = 0; + debug_assert!(imeta_data_import2::get_method_props( + metadata, staticMethod, + None, None, None, None, None, + Some(static_signature_ptr as *mut *const u8), Some(&mut static_signature_size), + None, None, + )); + let static_signature: &[u8] = &static_signature[..static_signature_size as usize]; + + unsafe { + if libc::memcmp( + static_signature.as_ptr().offset(1) as _, + method_signature.as_ptr() as _, + static_signature_size as usize, + ) != 0 { + continue; + } + } + *out_index = i; + return Some(InterfaceDeclaration::new(metadata, statics_token)); + } + } + + std::unreachable!(); + } + + + pub fn find_method_index(metadata: *mut IMetaDataImport2, class_token: mdTypeDef, method_token: mdMethodDef) -> usize { + let mut first_method = 0; + + let mut methods_enumerator = std::ptr::null_mut(); + let methods_enumerator_ptr = &mut methods_enumerator; + debug_assert!( + imeta_data_import2::enum_methods( + metadata, methods_enumerator_ptr, class_token, &mut first_method, 1, 0 as _, + ).is_ok() + ); + + imeta_data_import2::close_enum(metadata, methods_enumerator); + + + return (method_token - first_method) as usize; + } + + + pub fn declaring_interface_for_instance_method(metadata: *mut IMetaDataImport2, method_token: mdMethodDef, out_index: &mut usize) -> Option>> { + let class_token = DeclaringInterfaceForMethod::get_method_containing_class_token( + metadata, method_token, + ); + debug_assert!( + CorTokenType::from(enums::type_from_token(class_token)) == CorTokenType::mdtTypeDef + ); + let mut method_body_tokens = [0; 1024]; + let mut method_decl_tokens = [0; 1024]; + let mut method_impls_count = 0; + let mut method_impls_enumerator = std::ptr::null_mut(); + let method_impls_enumerator_ptr = &mut method_impls_enumerator; + debug_assert!( + imeta_data_import2::enum_method_impls( + metadata, method_impls_enumerator_ptr, Some(class_token), + Some(&mut method_body_tokens), + Some(&mut method_decl_tokens), + Some(method_body_tokens.len() as u32), + Some(&mut method_impls_count), + ).is_ok() + ); + + debug_assert!( + method_impls_count < (method_body_tokens.len() - 1) as u32 + ); + + imeta_data_import2::close_enum(metadata, method_impls_enumerator); + + let mut result: Option>> = None; + for i in 0..method_impls_count { + let method_body_token = method_body_tokens[i]; + debug_assert!( + CorTokenType::from(enums::type_from_token(method_body_token)) == CorTokenType::mdtMethodDef + ); + + if method_token != method_body_token { + continue; + } + + let method_decl_token = method_decl_tokens[i]; + match CorTokenType::from(enums::type_from_token(method_decl_token)) { + CorTokenType::mdtMethodDef => { + let mut declaring_interface_token = mdTokenNil; + debug_assert!( + imeta_data_import2::get_method_props( + metadata, method_decl_token, + Some(&mut declaring_interface_token), None, + None, None, None, None, + None, None, None, + ).is_ok() + ); + *out_index = DeclaringInterfaceForMethod::find_method_index( + metadata, declaring_interface_token, method_decl_token, + ); + result = Some( + Arc::new( + Mutex::new( + InterfaceDeclaration::new(metadata, declaring_interface_token) + ) + ) + ); + } + CorTokenType::mdtMemberRef => { + let mut parent_token = 0; + debug_assert!( + imeta_data_import2::get_member_ref_props( + metadata, method_decl_token, Some(&mut parent_token), None, + None, None, None, None, + ).is_ok() + ); + + match CorTokenType::from(enums::type_from_token(parent_token)) { + CorTokenType::mdtTypeRef => { + let mut external_metadata = std::ptr::null_mut(); + let external_metadata_ptr = &mut external_metadata; + let mut declaring_interface_token = 0; + let is_resolved = resolve_type_ref( + metadata, parent_token, external_metadata_ptr, &mut declaring_interface_token, + ); + debug_assert!( + is_resolved + ); + + let mut declaring_method_name = [0_u16; MAX_IDENTIFIER_LENGTH]; + let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; + let signature_ptr = &mut signature.as_mut_ptr(); + let mut signature_size = 0; + debug_assert!( + imeta_data_import2::get_member_ref_props( + metadata, method_decl_token, None, + Some(declaring_method_name.as_mut_ptr()), + Some(declaring_method_name.len() as u32), + None, Some(signature_ptr as *mut *const u8), Some(&mut signature_size), + ) + ); + let mut declaring_method = 0; + debug_assert!( + imeta_data_import2::find_method( + external_metadata as _, declaring_interface_token, declaring_method_name.as_mut_ptr(), Some(signature.as_ptr()), Some(signature_size), Some(&mut declaring_method), + ).is_ok() + ); + *out_index = DeclaringInterfaceForMethod::find_method_index( + external_metadata as _, declaring_interface_token, declaring_method, + ); + result = Some( + Arc::new( + Mutex::new( + InterfaceDeclaration::new(external_metadata as _, declaring_interface_token) + ) + ) + ); + } + CorTokenType::mdtTypeSpec => { + let mut type_spec_signature = std::ptr::null_mut(); + let type_spec_signature_ptr = &mut type_spec_signature; + let mut type_spec_signature_size = 0; + debug_assert!( + imeta_data_import2::get_type_spec_from_token( + metadata, parent_token, type_spec_signature_ptr as *mut *const u8, &mut type_spec_signature_size, + ).is_ok() + ); + + + let mut declaring_method_name = [0_u16; MAX_IDENTIFIER_LENGTH]; + let mut signature = std::ptr::null_mut(); + let signature_ptr = &mut signature; + let mut signature_size = 0; + debug_assert!( + imeta_data_import2::get_member_ref_props( + metadata, method_decl_token, None, Some( + declaring_method_name.as_mut_ptr() + ), + Some(declaring_method_name.len() as u32), + None, Some(signature_ptr as *mut *const u8), Some(&mut signature_size), + ).is_ok() + ); + let type1 = helpers::cor_sig_uncompress_element_type(type_spec_signature.as_ptr()); + debug_assert!( + type1 == crate::enums::CorElementType::ElementTypeGenericinst + ); + + let type2 = helpers::cor_sig_uncompress_element_type(type_spec_signature.as_ptr()); + debug_assert!( + type2 == crate::enums::CorElementType::ElementTypeClass + ); + + // TODO: Use signature in matching + let open_generic_class_token = helpers::cor_sig_uncompress_token(type_spec_signature.as_ptr()); + match CorTokenType::from(enums::type_from_token(open_generic_class_token)) { + CorTokenType::mdtTypeDef => { + let mut declaring_method = 0; + debug_assert!(imeta_data_import2::find_method( + metadata, open_generic_class_token, declaring_method_name.as_ptr(), None, None, Some(&mut declaring_method), + ).is_ok()); + *out_index = DeclaringInterfaceForMethod::find_method_index(metadata, open_generic_class_token, 0); + + result = Some( + Arc::new( + Mutex::new( + GenericInterfaceInstanceDeclaration::new( + metadata as _, open_generic_class_token, metadata as _, parent_token, + ) + ) + ) + ); + } + CorTokenType::mdtTypeRef => { + let mut external_metadata = std::ptr::null_mut(); + let mut external_metadata_ptr = &mut external_metadata; + let mut external_class_token = mdTokenNil; + + let is_resolved = resolve_type_ref( + metadata, open_generic_class_token, external_metadata_ptr, &mut external_class_token, + ); + debug_assert!( + is_resolved + ); + + let mut declaring_method = 0; + debug_assert!( + imeta_data_import2::find_method( + external_metadata as _, external_class_token, declaring_method_name.as_ptr(), None, None, Some(&mut declaring_method), + ).is_ok() + ); + + *out_index = DeclaringInterfaceForMethod::find_method_index(external_metadata as _, external_class_token, declaring_method); + result = Some( + Arc::new( + Mutex::new( + GenericInterfaceInstanceDeclaration::new(external_metadata, external_class_token, metadata as _, parent_token) + ) + ) + ); + } + _ => { + std::unreachable!() + } + } + } + _ => { + std::unreachable!() + } + } + } + _ => { + std::unreachable!(); + } + } + }; + result + } + + pub fn findDeclaringInterfaceForMethod(method: &MethodDeclaration, out_index: &mut usize) { + debug_assert!( + out_index + ); + + let metadata = method.base().metadata; + let method_token = method.base().token; + + if method.is_static() { + DeclaringInterfaceForMethod::declaring_interface_for_static_method( + metadata, method_token, out_index, + ); + } else if method.is_initializer() { + DeclaringInterfaceForMethod::declaring_interface_for_initializer( + metadata, method_token, out_index, + ) + } else { + DeclaringInterfaceForMethod::declaring_interface_for_instance_method( + metadata, method_token, out_index, + ) + } + } } \ No newline at end of file From d7726ff681a5ebb09fcb237a3df90b988d7a6906 Mon Sep 17 00:00:00 2001 From: Osei Fortune Date: Fri, 11 Jun 2021 15:08:03 -0400 Subject: [PATCH 09/11] updates --- core/src/metadata/com_helpers.rs | 2 +- .../declarations/base_class_declaration.rs | 12 ++++----- .../declarations/class_declaration.rs | 10 +++---- .../generic_delegate_declaration.rs | 7 +++-- .../generic_delegate_instance_declaration.rs | 4 +-- .../declarations/delegate_declaration/mod.rs | 8 +++--- .../generic_interface_declaration.rs | 6 ++--- .../generic_interface_instance_declaration.rs | 2 +- .../declaring_interface_for_method.rs | 26 ++++++++++++++----- 9 files changed, 44 insertions(+), 33 deletions(-) diff --git a/core/src/metadata/com_helpers.rs b/core/src/metadata/com_helpers.rs index a7852d1..559b64f 100755 --- a/core/src/metadata/com_helpers.rs +++ b/core/src/metadata/com_helpers.rs @@ -69,7 +69,7 @@ pub fn resolve_type_ref(metadata: *mut IMetaDataImport2, token: mdTypeRef, exter } -pub fn get_guid_attribute_value(metadata: *mut c_void, token: mdToken) -> GUID { +pub fn get_guid_attribute_value(metadata: *mut IMetaDataImport2, token: mdToken) -> GUID { debug_assert!(!metadata.is_null()); debug_assert!(token != mdTokenNil); let mut size = 0; diff --git a/core/src/metadata/declarations/base_class_declaration.rs b/core/src/metadata/declarations/base_class_declaration.rs index afd5e7d..7bd9623 100644 --- a/core/src/metadata/declarations/base_class_declaration.rs +++ b/core/src/metadata/declarations/base_class_declaration.rs @@ -62,7 +62,7 @@ impl<'a> BaseClassDeclaration<'a> { } fn make_method_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec> { - let mut enumerator = std::mem::MaybeUninit::uninit(); + let mut enumerator = std::ptr::null_mut(); let enumerator_ptr = &mut enumerator; let mut count = 0; let mut tokens = [0; 1024]; @@ -88,7 +88,7 @@ impl<'a> BaseClassDeclaration<'a> { } fn make_property_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec> { - let mut enumerator = std::mem::MaybeUninit::uninit(); + let mut enumerator = std::ptr::null_mut(); let enumerator_ptr = &mut enumerator; let mut count = 0; let mut tokens = [0; 1024]; @@ -113,7 +113,7 @@ impl<'a> BaseClassDeclaration<'a> { } fn make_event_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec> { - let mut enumerator = std::mem::MaybeUninit::uninit(); + let mut enumerator = std::ptr::null_mut(); let enumerator_ptr = &mut enumerator; let mut count = 0; let mut tokens = [0; 1024]; @@ -161,7 +161,7 @@ pub trait BaseClassDeclarationImpl { fn events<'a>(&self) -> &Vec>; - fn find_members_with_name(&self, name: &str) -> Vec> { + fn find_members_with_name(&self, name: &str) -> Vec { debug_assert!(!name.is_empty()); let mut result: Vec> = Vec::new(); @@ -209,7 +209,7 @@ pub trait BaseClassDeclarationImpl { debug_assert!(!name.is_empty()); let mut enumerator = std::mem::MaybeUninit::uninit(); - let enumerator_ptr = &mut enumerator; + let enumerator_ptr = &mut enumerator.as_mut_ptr(); let mut method_tokens: Vec = vec![0; 1024]; let mut methods_count = 0; let name = windows::HSTRING::from(name); @@ -221,7 +221,7 @@ pub trait BaseClassDeclarationImpl { method_tokens.as_mut_ptr(), method_tokens.len() as u32, &mut methods_count, ).is_ok() ); - imeta_data_import2::close_enum(base.metadata, enumerator); + imeta_data_import2::close_enum(base.metadata, enumerator.as_mut_ptr()); method_tokens.into_iter().map(|method_token| MethodDeclaration::new(base.metadata, method_token)).collect() } diff --git a/core/src/metadata/declarations/class_declaration.rs b/core/src/metadata/declarations/class_declaration.rs index b151219..f1c3d1e 100644 --- a/core/src/metadata/declarations/class_declaration.rs +++ b/core/src/metadata/declarations/class_declaration.rs @@ -24,9 +24,9 @@ pub struct ClassDeclaration<'a> { impl<'a> ClassDeclaration<'a> { - fn make_initializer_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec>{ + fn make_initializer_declarations<'b>(metadata: *mut IMetaDataImport2, token: mdTypeDef) -> Vec>{ let mut enumerator = std::mem::MaybeUninit::uninit(); - let enumerator_ptr = &mut enumerator; + let enumerator_ptr = &mut enumerator.as_mut_ptr(); let mut count = 0; let mut tokens = [0;1024]; @@ -41,7 +41,7 @@ impl<'a> ClassDeclaration<'a> { debug_assert!(count < (tokens.len() - 1) as u32); - imeta_data_import2::close_enum(metadata, enumerator); + imeta_data_import2::close_enum(metadata, enumerator.as_mut_ptr()); let mut result = Vec::new(); @@ -70,11 +70,11 @@ impl<'a> ClassDeclaration<'a> { return result; } - fn make_default_interface(metadata: *mut c_void, token: mdTypeDef) -> Arc> { + fn make_default_interface(metadata: *mut IMetaDataImport2, token: mdTypeDef) -> Arc> { let mut interface_impl_tokens = [0;1024]; let mut interface_impl_count = 0; let mut interface_enumerator = std::mem::MaybeUninit::uninit(); - let interface_enumerator_ptr = &mut interface_enumerator; + let interface_enumerator_ptr = &mut interface_enumerator.as_mut_ptr(); debug_assert!( imeta_data_import2::enum_interface_impls( metadata, interface_enumerator_ptr, Some(token), diff --git a/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs b/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs index 83eb6cc..4ea4142 100644 --- a/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs +++ b/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs @@ -1,11 +1,10 @@ use std::borrow::Cow; -use core_bindings::{mdToken}; +use core_bindings::{mdToken, IMetaDataImport2}; use crate::bindings::imeta_data_import2; use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; use crate::metadata::declarations::delegate_declaration::{DelegateDeclaration, DelegateDeclarationImpl}; -use crate::prelude::c_void; use crate::metadata::declarations::method_declaration::MethodDeclaration; use crate::metadata::declarations::type_declaration::TypeDeclaration; @@ -15,7 +14,7 @@ pub struct GenericDelegateDeclaration<'a> { } impl<'a> GenericDelegateDeclaration<'a> { - pub fn new(metadata: *mut c_void, token: mdToken) -> Self { + pub fn new(metadata: *mut IMetaDataImport2, token: mdToken) -> Self { Self { base: DelegateDeclaration::new_overload( DeclarationKind::GenericDelegate, metadata, token, @@ -26,7 +25,7 @@ impl<'a> GenericDelegateDeclaration<'a> { pub fn number_of_generic_parameters(&self) -> usize { let mut count = 0; - let mut enumerator = std::mem::MaybeUninit::uninit(); + let mut enumerator = std::ptr::null_mut(); let enumerator_ptr = &mut enumerator; debug_assert!( diff --git a/core/src/metadata/declarations/delegate_declaration/generic_delegate_instance_declaration.rs b/core/src/metadata/declarations/delegate_declaration/generic_delegate_instance_declaration.rs index 371c8cc..653a3cd 100644 --- a/core/src/metadata/declarations/delegate_declaration/generic_delegate_instance_declaration.rs +++ b/core/src/metadata/declarations/delegate_declaration/generic_delegate_instance_declaration.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use core_bindings::{mdTypeDef, mdTypeSpec}; +use core_bindings::{mdTypeDef, mdTypeSpec, IMetaDataImport2}; use crate::bindings::{enums, imeta_data_import2}; use crate::enums::CorTokenType; @@ -20,7 +20,7 @@ pub struct GenericDelegateInstanceDeclaration<'a> { } impl<'a> GenericDelegateInstanceDeclaration<'a> { - pub fn new(open_metadata: *mut c_void, open_token: mdTypeDef, closed_metadata: *mut c_void, closed_token: mdTypeSpec) -> Self { + pub fn new(open_metadata: *mut IMetaDataImport2, open_token: mdTypeDef, closed_metadata: *mut c_void, closed_token: mdTypeSpec) -> Self { debug_assert!(!closed_metadata.is_null()); debug_assert!(CorTokenType::from(enums::type_from_token(closed_token)) == CorTokenType::mdtTypeSpec); debug_assert!(closed_token != mdTypeSpecNil); diff --git a/core/src/metadata/declarations/delegate_declaration/mod.rs b/core/src/metadata/declarations/delegate_declaration/mod.rs index bb2394a..21cc058 100644 --- a/core/src/metadata/declarations/delegate_declaration/mod.rs +++ b/core/src/metadata/declarations/delegate_declaration/mod.rs @@ -15,12 +15,12 @@ pub mod generic_delegate_instance_declaration; const INVOKE_METHOD_NAME: &str = "Invoke"; -pub fn get_invoke_method_token(meta_data: *mut c_void, token: mdTypeDef) -> mdMethodDef { +pub fn get_invoke_method_token(meta_data: *mut IMetaDataImport2, token: mdTypeDef) -> mdMethodDef { let mut invoke_method_token = mdTokenNil; let string = windows::HSTRING::from(INVOKE_METHOD_NAME); debug_assert!( imeta_data_import2::find_method( - meta_data, token, string.as_wide().as_ptr(), None, 0, &mut invoke_method_token, + meta_data, token, string.as_wide().as_ptr(), None, None, Some(&mut invoke_method_token), ).is_ok() ); return invoke_method_token; @@ -41,13 +41,13 @@ pub struct DelegateDeclaration<'a> { } impl<'a> DelegateDeclaration<'a> { - pub fn new(metadata: *mut c_void, token: mdTypeDef) -> Self { + pub fn new(metadata: *mut IMetaDataImport2, token: mdTypeDef) -> Self { Self::new_overload( DeclarationKind::Delegate, metadata, token, ) } - pub fn new_overload(kind: DeclarationKind, metadata: *mut c_void, token: mdTypeDef) -> Self { + pub fn new_overload(kind: DeclarationKind, metadata: *mut IMetaDataImport2, token: mdTypeDef) -> Self { Self { base: TypeDeclaration::new( kind, metadata, token, diff --git a/core/src/metadata/declarations/interface_declaration/generic_interface_declaration.rs b/core/src/metadata/declarations/interface_declaration/generic_interface_declaration.rs index 9552a24..35419e8 100644 --- a/core/src/metadata/declarations/interface_declaration/generic_interface_declaration.rs +++ b/core/src/metadata/declarations/interface_declaration/generic_interface_declaration.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use core_bindings::{GUID, mdToken}; +use core_bindings::{GUID, mdToken, IMetaDataImport2}; use crate::bindings::imeta_data_import2; use crate::metadata::declarations::base_class_declaration::BaseClassDeclarationImpl; @@ -18,7 +18,7 @@ pub struct GenericInterfaceDeclaration<'a> { } impl<'a> GenericInterfaceDeclaration<'a> { - pub fn new(metadata: *mut c_void, token: mdToken) -> Self { + pub fn new(metadata: *mut IMetaDataImport2, token: mdToken) -> Self { Self { base: InterfaceDeclaration::new_with_kind(DeclarationKind::GenericInterface, metadata, token) } @@ -26,7 +26,7 @@ impl<'a> GenericInterfaceDeclaration<'a> { pub fn number_of_generic_parameters(&self) -> usize { let mut count = 0; - let mut enumerator = std::mem::MaybeUninit::uninit(); + let mut enumerator = std::ptr::null_mut(); let enumerator_ptr = &mut enumerator; let base = self.base.base.base(); debug_assert!( diff --git a/core/src/metadata/declarations/interface_declaration/generic_interface_instance_declaration.rs b/core/src/metadata/declarations/interface_declaration/generic_interface_instance_declaration.rs index be4a6bf..180a018 100644 --- a/core/src/metadata/declarations/interface_declaration/generic_interface_instance_declaration.rs +++ b/core/src/metadata/declarations/interface_declaration/generic_interface_instance_declaration.rs @@ -25,7 +25,7 @@ pub struct GenericInterfaceInstanceDeclaration<'a> { } impl<'a> GenericInterfaceInstanceDeclaration<'a> { - pub fn new(open_metadata: *mut c_void, open_token: mdTypeDef, closed_metadata: *mut c_void, closed_token: mdTypeSpec) -> Self { + pub fn new(open_metadata: *mut IMetaDataImport2, open_token: mdTypeDef, closed_metadata: *mut c_void, closed_token: mdTypeSpec) -> Self { debug_assert!(!closed_metadata.is_null()); debug_assert!(CorTokenType::from(enums::type_from_token(closed_token)) == CorTokenType::mdtTypeSpec); debug_assert!(closed_token != mdTypeSpecNil); diff --git a/core/src/metadata/declaring_interface_for_method.rs b/core/src/metadata/declaring_interface_for_method.rs index 47554dd..5d0e0ef 100644 --- a/core/src/metadata/declaring_interface_for_method.rs +++ b/core/src/metadata/declaring_interface_for_method.rs @@ -221,7 +221,7 @@ impl DeclaringInterfaceForMethod { } - pub fn declaring_interface_for_initializer<'a>(metadata: *mut IMetaDataImport2, method_token: mdMethodDef, out_index: &mut usize) -> Option> { + pub fn declaring_interface_for_initializer<'a>(metadata: *mut IMetaDataImport2, method_token: mdMethodDef, out_index: &mut usize) -> Option>> { // InterfaceDeclaration let method_argument_count = DeclaringInterfaceForMethod::get_method_argument_count(metadata, method_token); @@ -251,7 +251,13 @@ impl DeclaringInterfaceForMethod { } *out_index = i; - return Some(InterfaceDeclaration::new(metadata, factory_token)); + return Some( + Arc::new( + Mutex::new( + InterfaceDeclaration::new(metadata, factory_token) + ) + ) + ); } } @@ -290,7 +296,13 @@ impl DeclaringInterfaceForMethod { } *out_index = i; - return Some(InterfaceDeclaration::new(metadata, factory_token)); + return Some( + Arc::new( + Mutex::new( + InterfaceDeclaration::new(metadata, factory_token) + ) + ) + ); } } @@ -299,7 +311,7 @@ impl DeclaringInterfaceForMethod { } - pub fn declaring_interface_for_static_method<'a>(metadata: *mut IMetaDataImport2, method_token: mdMethodDef, out_index: &mut usize) -> Option> { + pub fn declaring_interface_for_static_method<'a>(metadata: *mut IMetaDataImport2, method_token: mdMethodDef, out_index: &mut usize) -> Option>> { let method_signature = DeclaringInterfaceForMethod::get_method_signature( metadata, method_token, ); @@ -345,7 +357,7 @@ impl DeclaringInterfaceForMethod { } } *out_index = i; - return Some(InterfaceDeclaration::new(metadata, statics_token)); + return Some(Arc::new(Mutex::new(InterfaceDeclaration::new(metadata, statics_token)))); } } @@ -583,7 +595,7 @@ impl DeclaringInterfaceForMethod { result } - pub fn findDeclaringInterfaceForMethod(method: &MethodDeclaration, out_index: &mut usize) { + pub fn find_declaring_interface_for_method(method: &MethodDeclaration, out_index: &mut usize) -> Option>> { debug_assert!( out_index ); @@ -594,7 +606,7 @@ impl DeclaringInterfaceForMethod { if method.is_static() { DeclaringInterfaceForMethod::declaring_interface_for_static_method( metadata, method_token, out_index, - ); + ) } else if method.is_initializer() { DeclaringInterfaceForMethod::declaring_interface_for_initializer( metadata, method_token, out_index, From 77b5d5425194b3c3bde9748556302840885161a4 Mon Sep 17 00:00:00 2001 From: Osei Fortune Date: Sat, 12 Jun 2021 18:10:26 -0400 Subject: [PATCH 10/11] updates --- core/src/metadata/declaration_factory.rs | 16 ++++++---- .../declarations/base_class_declaration.rs | 23 +++++++------- .../generic_delegate_declaration.rs | 23 +++++++------- .../generic_delegate_instance_declaration.rs | 21 ++++++------- .../declarations/delegate_declaration/mod.rs | 23 +++++++------- .../metadata/declarations/enum_declaration.rs | 15 +++++----- .../declarations/method_declaration.rs | 22 +++++++------- .../declarations/struct_declaration.rs | 24 ++++++++------- .../declarations/struct_field_declaration.rs | 10 +++---- .../metadata/declarations/type_declaration.rs | 26 +++++++++------- core/src/metadata/meta_data_reader.rs | 30 +++++++++++++------ core/src/metadata/signature.rs | 2 +- core/src/prelude.rs | 23 ++++++++++++-- core/src/runtime/com/com_constructor.rs | 2 ++ core/src/runtime/com/com_interop.rs | 6 ++++ core/src/runtime/com/com_method_call.rs | 2 ++ core/src/runtime/com/com_object_wrapper.rs | 2 ++ core/src/runtime/com/com_unknown_type.rs | 2 ++ core/src/runtime/com/mod.rs | 5 ++++ core/src/runtime/console.rs | 2 +- core/src/runtime/ffi/ff_boolean_type.rs | 2 ++ core/src/runtime/ffi/ffi_interop.rs | 1 + core/src/runtime/ffi/ffi_number_type.rs | 2 ++ core/src/runtime/ffi/ffi_void_type.rs | 2 ++ core/src/runtime/ffi/mod.rs | 4 +++ core/src/runtime/mod.rs | 14 ++++++++- 26 files changed, 197 insertions(+), 107 deletions(-) create mode 100644 core/src/runtime/com/com_constructor.rs create mode 100644 core/src/runtime/com/com_interop.rs create mode 100644 core/src/runtime/com/com_method_call.rs create mode 100644 core/src/runtime/com/com_object_wrapper.rs create mode 100644 core/src/runtime/com/com_unknown_type.rs create mode 100644 core/src/runtime/ffi/ff_boolean_type.rs create mode 100644 core/src/runtime/ffi/ffi_interop.rs create mode 100644 core/src/runtime/ffi/ffi_number_type.rs create mode 100644 core/src/runtime/ffi/ffi_void_type.rs diff --git a/core/src/metadata/declaration_factory.rs b/core/src/metadata/declaration_factory.rs index bbf3a5d..7745212 100644 --- a/core/src/metadata/declaration_factory.rs +++ b/core/src/metadata/declaration_factory.rs @@ -14,16 +14,20 @@ use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; pub struct DeclarationFactory {} impl DeclarationFactory { - pub fn make_delegate_declaration<'b>(metadata: *mut c_void, token: mdToken) -> Box { + pub fn make_delegate_declaration<'b>(metadata: Arc>, token: mdToken) -> Box { match CorTokenType::from(enums::type_from_token(token)) { CorTokenType::mdtTypeDef => Box::new(DelegateDeclaration::new(metadata, token)), CorTokenType::mdtTypeRef => { + let metadata = get_mutex_value_mut(&metadata); let mut external_metadata = std::mem::MaybeUninit::uninit(); + let external_metadata_ptr = &mut external_metadata.as_ptr(); let mut external_delegate_token = mdTokenNil; - let is_resolved = resolve_type_ref(metadata, token, &mut external_metadata, &mut external_delegate_token); + let is_resolved = resolve_type_ref(metadata, token, external_metadata_ptr as *mut *mut c_void, &mut external_delegate_token); debug_assert!(is_resolved); - Box::new(DelegateDeclaration::new(external_metadata, external_delegate_token)) + Box::new(DelegateDeclaration::new(Arc::new(Mutex::new( + unsafe { external_metadata.assume_init() } + )), external_delegate_token)) } CorTokenType::mdtTypeSpec => { let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; @@ -51,8 +55,8 @@ impl DeclarationFactory { Box::new(GenericDelegateInstanceDeclaration::new(metadata, open_generic_delegate_token, metadata, token)) } CorTokenType::mdtTypeRef => { - let mut external_metadata = std::mem::MaybeUninit::uninit(); - let external_metadata_ptr = &mut external_metadata; + let mut external_metadata: std::mem::MaybeUninit = std::mem::MaybeUninit::uninit(); + let external_metadata_ptr = &mut external_metadata.as_mut_ptr(); let mut external_delegate_token = mdTokenNil; let is_resolved = resolve_type_ref( @@ -72,7 +76,7 @@ impl DeclarationFactory { } } } - pub fn make_interface_declaration(metadata: *mut c_void, token: mdToken) -> Arc> { + pub fn make_interface_declaration(metadata: Arc>, token: mdToken) -> Arc> { match CorTokenType::from(enums::type_from_token(token)) { CorTokenType::mdtTypeDef => { Arc::new( diff --git a/core/src/metadata/declarations/base_class_declaration.rs b/core/src/metadata/declarations/base_class_declaration.rs index 7bd9623..55dc031 100644 --- a/core/src/metadata/declarations/base_class_declaration.rs +++ b/core/src/metadata/declarations/base_class_declaration.rs @@ -18,29 +18,30 @@ use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; #[derive(Clone)] -pub struct BaseClassDeclaration<'a> { - base: TypeDeclaration<'a>, +pub struct BaseClassDeclaration { + base: TypeDeclaration, implemented_interfaces: Vec>>, - methods: Vec>, - properties: Vec>, - events: Vec>, + methods: Vec, + properties: Vec, + events: Vec, } -impl<'a> BaseClassDeclaration<'a> { - fn make_implemented_interfaces_declarations(metadata: *mut IMetaDataImport2, token: mdTypeDef) -> Vec>> { +impl BaseClassDeclaration { + fn make_implemented_interfaces_declarations(metadata: Arc>, token: mdTypeDef) -> Vec>> { let mut enumerator = std::ptr::null_mut(); let enumerator_ptr = &mut enumerator; let mut count = 0; let mut tokens = [0; 1024]; + let metadata_inner = get_mutex_value_mut(&metadata); debug_assert!( imeta_data_import2::enum_interface_impls( - metadata, enumerator_ptr, Some(token), Some(tokens.as_mut_ptr()), Some(tokens.len() as u32), Some(&mut count), + metadata_inner, enumerator_ptr, Some(token), Some(tokens.as_mut_ptr()), Some(tokens.len() as u32), Some(&mut count), ).is_ok() ); debug_assert!(count < (tokens.len() - 1) as u32); - imeta_data_import2::close_enum(metadata, enumerator); + imeta_data_import2::close_enum(metadata_inner, enumerator); let mut result = Vec::new(); @@ -48,12 +49,12 @@ impl<'a> BaseClassDeclaration<'a> { let mut interface_token = mdTokenNil; debug_assert!( imeta_data_import2::get_interface_impl_props( - metadata, *token, None, Some(&mut interface_token), + metadata_inner, *token, None, Some(&mut interface_token), ).is_ok() ); result.push( DeclarationFactory::make_interface_declaration( - metadata, interface_token, + metadata_inner, interface_token, ) ); } diff --git a/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs b/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs index 4ea4142..51acfaf 100644 --- a/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs +++ b/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs @@ -7,14 +7,15 @@ use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; use crate::metadata::declarations::delegate_declaration::{DelegateDeclaration, DelegateDeclarationImpl}; use crate::metadata::declarations::method_declaration::MethodDeclaration; use crate::metadata::declarations::type_declaration::TypeDeclaration; +use std::sync::{Arc, Mutex}; #[derive(Clone, Debug)] -pub struct GenericDelegateDeclaration<'a> { - base: DelegateDeclaration<'a>, +pub struct GenericDelegateDeclaration { + base: DelegateDeclaration, } -impl<'a> GenericDelegateDeclaration<'a> { - pub fn new(metadata: *mut IMetaDataImport2, token: mdToken) -> Self { +impl GenericDelegateDeclaration { + pub fn new(metadata: Arc>, token: mdToken) -> Self { Self { base: DelegateDeclaration::new_overload( DeclarationKind::GenericDelegate, metadata, token, @@ -29,18 +30,18 @@ impl<'a> GenericDelegateDeclaration<'a> { let enumerator_ptr = &mut enumerator; debug_assert!( - imeta_data_import2::enum_generic_params(self.base.base.metadata, enumerator_ptr, self.base.base.token, None, None, None).is_ok() + imeta_data_import2::enum_generic_params(self.base.base.metadata_mut(), enumerator_ptr, self.base.base.token, None, None, None).is_ok() ); debug_assert!( - imeta_data_import2::count_enum(self.base.base.metadata, enumerator, &mut count).is_ok() + imeta_data_import2::count_enum(self.base.base.metadata_mut(), enumerator, &mut count).is_ok() ); - imeta_data_import2::close_enum(self.base.base.metadata, enumerator); + imeta_data_import2::close_enum(self.base.base.metadata_mut(), enumerator); return count as usize; } } -impl<'a> Declaration for GenericDelegateDeclaration<'a> { +impl Declaration for GenericDelegateDeclaration { fn name<'b>(&self) -> Cow<'b, str> { self.base.name() } @@ -54,12 +55,12 @@ impl<'a> Declaration for GenericDelegateDeclaration<'a> { } } -impl<'a> DelegateDeclarationImpl for GenericDelegateDeclaration<'a> { - fn base(&self) -> &TypeDeclaration { +impl DelegateDeclarationImpl for GenericDelegateDeclaration { + fn base<'b>(&self) -> &'b TypeDeclaration { &self.base.base } - fn invoke_method(&self) -> &MethodDeclaration { + fn invoke_method<'b>(&self) -> &'b MethodDeclaration { &self.base.invoke_method } } \ No newline at end of file diff --git a/core/src/metadata/declarations/delegate_declaration/generic_delegate_instance_declaration.rs b/core/src/metadata/declarations/delegate_declaration/generic_delegate_instance_declaration.rs index 653a3cd..182d2f6 100644 --- a/core/src/metadata/declarations/delegate_declaration/generic_delegate_instance_declaration.rs +++ b/core/src/metadata/declarations/delegate_declaration/generic_delegate_instance_declaration.rs @@ -8,19 +8,20 @@ use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; use crate::metadata::declarations::delegate_declaration::{DelegateDeclaration, DelegateDeclarationImpl}; use crate::metadata::generic_instance_id_builder::GenericInstanceIdBuilder; use crate::metadata::signature::Signature; -use crate::prelude::{c_void, CLSID, MAX_IDENTIFIER_LENGTH, mdTypeSpecNil}; +use crate::prelude::*; use crate::metadata::declarations::method_declaration::MethodDeclaration; use crate::metadata::declarations::type_declaration::TypeDeclaration; +use std::sync::{Arc, Mutex}; #[derive(Clone, Debug)] -pub struct GenericDelegateInstanceDeclaration<'a> { - base: DelegateDeclaration<'a>, +pub struct GenericDelegateInstanceDeclaration { + base: DelegateDeclaration, closed_token: mdTypeSpec, - closed_metadata: *mut c_void, + closed_metadata: Arc>, } -impl<'a> GenericDelegateInstanceDeclaration<'a> { - pub fn new(open_metadata: *mut IMetaDataImport2, open_token: mdTypeDef, closed_metadata: *mut c_void, closed_token: mdTypeSpec) -> Self { +impl GenericDelegateInstanceDeclaration { + pub fn new(open_metadata: Arc>, open_token: mdTypeDef, closed_metadata: Arc>, closed_token: mdTypeSpec) -> Self { debug_assert!(!closed_metadata.is_null()); debug_assert!(CorTokenType::from(enums::type_from_token(closed_token)) == CorTokenType::mdtTypeSpec); debug_assert!(closed_token != mdTypeSpecNil); @@ -35,7 +36,7 @@ impl<'a> GenericDelegateInstanceDeclaration<'a> { } } -impl<'a> Declaration for GenericDelegateInstanceDeclaration<'a> { +impl Declaration for GenericDelegateInstanceDeclaration { fn name<'b>(&self) -> Cow<'b, str> { self.base.name() } @@ -59,8 +60,8 @@ impl<'a> Declaration for GenericDelegateInstanceDeclaration<'a> { } -impl<'a> DelegateDeclarationImpl for GenericDelegateInstanceDeclaration<'a> { - fn base(&self) -> &TypeDeclaration { +impl DelegateDeclarationImpl for GenericDelegateInstanceDeclaration { + fn base<'b>(&self) -> &'b TypeDeclaration { &self.base.base } @@ -68,7 +69,7 @@ impl<'a> DelegateDeclarationImpl for GenericDelegateInstanceDeclaration<'a> { GenericInstanceIdBuilder::generate_id(self) } - fn invoke_method(&self) -> &MethodDeclaration<'a> { + fn invoke_method<'b>(&self) -> &MethodDeclaration<'b> { &self.base.invoke_method } } \ No newline at end of file diff --git a/core/src/metadata/declarations/delegate_declaration/mod.rs b/core/src/metadata/declarations/delegate_declaration/mod.rs index 21cc058..a6cc91c 100644 --- a/core/src/metadata/declarations/delegate_declaration/mod.rs +++ b/core/src/metadata/declarations/delegate_declaration/mod.rs @@ -8,6 +8,7 @@ use crate::{ metadata::declarations::type_declaration::TypeDeclaration, prelude::*, }; +use std::sync::{Arc, Mutex}; pub mod generic_delegate_declaration; @@ -29,25 +30,25 @@ pub fn get_invoke_method_token(meta_data: *mut IMetaDataImport2, token: mdTypeDe pub trait DelegateDeclarationImpl { fn base(&self) -> &TypeDeclaration; fn id(&self) -> GUID { - get_guid_attribute_value(self.base().metadata, self.base().token) + get_guid_attribute_value(self.base().metadata_mut(), self.base().token) } fn invoke_method(&self) -> &MethodDeclaration; } #[derive(Clone, Debug)] -pub struct DelegateDeclaration<'a> { - base: TypeDeclaration<'a>, - invoke_method: MethodDeclaration<'a>, +pub struct DelegateDeclaration { + base: TypeDeclaration, + invoke_method: MethodDeclaration, } -impl<'a> DelegateDeclaration<'a> { - pub fn new(metadata: *mut IMetaDataImport2, token: mdTypeDef) -> Self { +impl<'a> DelegateDeclaration { + pub fn new(metadata: Arc>, token: mdTypeDef) -> Self { Self::new_overload( DeclarationKind::Delegate, metadata, token, ) } - pub fn new_overload(kind: DeclarationKind, metadata: *mut IMetaDataImport2, token: mdTypeDef) -> Self { + pub fn new_overload(kind: DeclarationKind, metadata: Arc>, token: mdTypeDef) -> Self { Self { base: TypeDeclaration::new( kind, metadata, token, @@ -59,7 +60,7 @@ impl<'a> DelegateDeclaration<'a> { } } -impl<'a> Declaration for DelegateDeclaration<'a> { +impl Declaration for DelegateDeclaration { fn name<'b>(&self) -> Cow<'b, str> { self.base.name() } @@ -74,12 +75,12 @@ impl<'a> Declaration for DelegateDeclaration<'a> { } -impl<'a> DelegateDeclarationImpl for DelegateDeclaration<'a> { - fn base(&self) -> &TypeDeclaration<'a> { +impl DelegateDeclarationImpl for DelegateDeclaration { + fn base<'b>(&self) -> &'b TypeDeclaration { &self.base } - fn invoke_method(&self) -> &MethodDeclaration<'a> { + fn invoke_method<'b>(&self) -> &'b MethodDeclaration { &self.invoke_method } } \ No newline at end of file diff --git a/core/src/metadata/declarations/enum_declaration.rs b/core/src/metadata/declarations/enum_declaration.rs index 1ad6a6d..c1b1831 100644 --- a/core/src/metadata/declarations/enum_declaration.rs +++ b/core/src/metadata/declarations/enum_declaration.rs @@ -10,13 +10,14 @@ use super::{ type_declaration::TypeDeclaration, }; use std::borrow::Cow; +use std::sync::{Arc, Mutex}; #[derive(Debug)] -pub struct EnumDeclaration<'a> { - base: TypeDeclaration<'a>, +pub struct EnumDeclaration { + base: TypeDeclaration, } -impl<'a> Declaration for EnumDeclaration<'a> { +impl Declaration for EnumDeclaration { fn is_exported(&self) -> bool { self.base.is_exported() } @@ -34,8 +35,8 @@ impl<'a> Declaration for EnumDeclaration<'a> { } } -impl<'a> EnumDeclaration<'a> { - pub fn new(metadata: *mut c_void, token: mdTypeDef) -> Self { +impl EnumDeclaration { + pub fn new(metadata: Arc>, token: mdTypeDef) -> Self { Self { base: TypeDeclaration::new(DeclarationKind::Enum, metadata, token) } @@ -45,14 +46,14 @@ impl<'a> EnumDeclaration<'a> { let mut type_field = mdTokenNil; let name_w = OsString::from(COR_ENUM_FIELD_NAME).to_wide(); debug_assert!(imeta_data_import2::find_field( - self.base.metadata, self.base.token, + self.base.metadata_mut(), self.base.token, Some(name_w.as_ptr()), None, None, Some(&mut type_field), ).is_ok()); let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; let mut signature_size = 0; debug_assert!( imeta_data_import2::get_field_props( - self.base.metadata, + self.base.metadata_mut(), type_field, None, None, None, None, None, Some(&mut signature.as_mut_ptr() as _ as *mut *const u8), diff --git a/core/src/metadata/declarations/method_declaration.rs b/core/src/metadata/declarations/method_declaration.rs index 07b7488..726d65f 100644 --- a/core/src/metadata/declarations/method_declaration.rs +++ b/core/src/metadata/declarations/method_declaration.rs @@ -11,34 +11,36 @@ use crate::enums::CorCallingConvention; use crate::metadata::com_helpers::get_unary_custom_attribute_string_value; use crate::metadata::declarations::parameter_declaration::ParameterDeclaration; use std::borrow::Cow; +use std::sync::{Arc, Mutex}; #[derive(Clone, Debug)] -pub struct MethodDeclaration <'a> { - base: TypeDeclaration<'a>, - parameters: Vec>, +pub struct MethodDeclaration { + base: TypeDeclaration, + parameters: Vec, } const OVERLOAD_ATTRIBUTE: &str = "Windows.Foundation.Metadata.OverloadAttribute"; const DEFAULT_OVERLOAD_ATTRIBUTE: &str ="Windows.Foundation.Metadata.DefaultOverloadAttribute"; -impl<'a> MethodDeclaration <'a> { - pub fn base (&self) -> &TypeDeclaration<'a> { +impl MethodDeclaration { + pub fn base <'b>(&self) -> &'b TypeDeclaration { &self.base } - pub fn new(metadata: *mut c_void, token: mdMethodDef) -> Self { + pub fn new(metadata: Arc>, token: mdMethodDef) -> Self { debug_assert!(!metadata.is_null()); debug_assert!(enums::type_from_token(token) == CorTokenType::mdtMethodDef as u32); assert!(token != mdMethodDefNil); let mut signature = std::mem::MaybeUninit::uninit(); - let mut signature_ptr = &mut signature; + let mut signature_ptr = &mut signature.as_mut_ptr(); let mut signature_size: ULONG = 0; + debug_assert!( imeta_data_import2::get_method_props( metadata, token, None, None, None, - None,None,Some(signature), Some(&mut signature_size), + None,None,Some(signature_ptr as *mut *const u8), Some(&mut signature_size), None,None ).is_ok() ); @@ -55,9 +57,9 @@ impl<'a> MethodDeclaration <'a> { std::unimplemented!() } - let mut arguments_count = { helpers::cor_sig_uncompress_data(signature as *const u8) }; + let mut arguments_count = { helpers::cor_sig_uncompress_data(signature.as_ptr()) }; - let return_type = Signature::consume_type(signature as *const u8); + let return_type = Signature::consume_type(signature.as_ptr()); let mut parameters: Vec = Vec::new(); let mut parameter_enumerator = std::mem::MaybeUninit::uninit(); diff --git a/core/src/metadata/declarations/struct_declaration.rs b/core/src/metadata/declarations/struct_declaration.rs index 3a01c14..75d0e7e 100644 --- a/core/src/metadata/declarations/struct_declaration.rs +++ b/core/src/metadata/declarations/struct_declaration.rs @@ -4,14 +4,15 @@ use crate::metadata::declarations::type_declaration::TypeDeclaration; use crate::bindings::imeta_data_import2; use crate::metadata::declarations::struct_field_declaration::StructFieldDeclaration; use std::borrow::Cow; +use std::sync::{Arc, Mutex}; #[derive(Clone, Debug)] -pub struct StructDeclaration<'a> { - base: TypeDeclaration<'a>, - fields: Vec>, +pub struct StructDeclaration { + base: TypeDeclaration, + fields: Vec, } -impl<'a> Declaration for StructDeclaration<'a> { +impl Declaration for StructDeclaration { fn name<'b>(&self) -> Cow<'b, str> { self.base.name() } @@ -25,8 +26,8 @@ impl<'a> Declaration for StructDeclaration<'a> { } } -impl<'a> StructDeclaration<'a> { - pub fn new(metadata: *mut c_void, token: mdTypeDef, +impl StructDeclaration { + pub fn new(metadata: Arc>, token: mdTypeDef, ) -> Self { Self { base: TypeDeclaration::new( @@ -44,26 +45,27 @@ impl<'a> StructDeclaration<'a> { self.fields.as_slice() } - fn make_field_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec> { - let mut enumerator = std::mem::MaybeUninit::uninit(); + fn make_field_declarations<'b>(metadata: Arc>, token: mdTypeDef) -> Vec> { + let metadata_inner = get_mutex_value_mut(&metadata); + let mut enumerator = std::ptr::null_mut(); let mut count = 0; let mut tokens = [0; 1024]; let mut enumerator_ptr = &mut enumerator; debug_assert!( imeta_data_import2::enum_fields( - metadata, enumerator_ptr, token, tokens.as_mut_ptr(), tokens.len() as u32, &mut count, + metadata_inner, enumerator_ptr, token, tokens.as_mut_ptr(), tokens.len() as u32, &mut count, ).is_ok() ); debug_assert!(count < (tokens.len() - 1) as u32); - imeta_data_import2::close_enum(metadata, enumerator); + imeta_data_import2::close_enum(metadata_inner, enumerator); let mut result = Vec::new(); for i in 0..count { result.push( - StructFieldDeclaration::new(metadata, tokens[i]) + StructFieldDeclaration::new(Arc::clone(&metadata), tokens[i]) ) } diff --git a/core/src/metadata/declarations/struct_field_declaration.rs b/core/src/metadata/declarations/struct_field_declaration.rs index 86552fb..e4f25ce 100644 --- a/core/src/metadata/declarations/struct_field_declaration.rs +++ b/core/src/metadata/declarations/struct_field_declaration.rs @@ -6,11 +6,11 @@ use std::borrow::Cow; #[derive(Clone,Debug)] -pub struct StructFieldDeclaration<'a> { - base: FieldDeclaration<'a>, +pub struct StructFieldDeclaration { + base: FieldDeclaration, } -impl<'a> Declaration for StructFieldDeclaration <'a>{ +impl Declaration for StructFieldDeclaration{ fn name<'b>(&self) -> Cow<'b, str> { self.base.name() } @@ -24,11 +24,11 @@ impl<'a> Declaration for StructFieldDeclaration <'a>{ } } -impl<'a> StructFieldDeclaration<'a> { +impl StructFieldDeclaration { pub fn base(&self)-> &FieldDeclaration { &self.base } - pub fn new(metadata: *mut c_void, token: mdFieldDef) -> Self { + pub fn new(metadata: IMetaDataImport2, token: mdFieldDef) -> Self { Self { base: FieldDeclaration::new( DeclarationKind::StructField, diff --git a/core/src/metadata/declarations/type_declaration.rs b/core/src/metadata/declarations/type_declaration.rs index 39c4d75..086ea65 100644 --- a/core/src/metadata/declarations/type_declaration.rs +++ b/core/src/metadata/declarations/type_declaration.rs @@ -7,25 +7,26 @@ use crate::{ }, }; pub use super::declaration::{Declaration, DeclarationKind}; -use std::marker; + use std::ffi::{OsString}; use std::borrow::Cow; +use std::sync::{Arc, Mutex}; #[derive(Clone, Debug)] -pub struct TypeDeclaration<'a> { +pub struct TypeDeclaration { pub kind: DeclarationKind, - pub metadata: *mut IMetaDataImport2, + pub metadata: Arc>, pub token: mdTypeDef, - _marker: marker::PhantomData<&'a ()>, } -impl<'a> Declaration for TypeDeclaration<'a> { +impl Declaration for TypeDeclaration { fn is_exported(&self) -> bool { let mut flags: DWORD = 0; + debug_assert!( imeta_data_import2::get_type_def_props( - self.metadata, self.token, None, None, None, Some(&mut flags), None, + self.metadata_mut(), self.token, None, None, None, Some(&mut flags), None, ).is_ok() ); @@ -63,7 +64,7 @@ impl<'a> Declaration for TypeDeclaration<'a> { fn full_name<'b>(&self) -> Cow<'b, str> { let mut full_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; - let length = helpers::get_type_name(self.metadata, self.token, full_name_data.as_mut_ptr(), full_name_data.len() as u32); + let length = helpers::get_type_name(self.metadata_mut(), self.token, full_name_data.as_mut_ptr(), full_name_data.len() as u32); OsString::from_wide(&full_name_data[..length as usize]).to_string_lossy() } @@ -72,13 +73,18 @@ impl<'a> Declaration for TypeDeclaration<'a> { } } -impl<'a> TypeDeclaration<'a> { - pub fn new(kind: DeclarationKind, metadata: *mut IMetaDataImport2, token: mdTypeDef) -> Self { +impl TypeDeclaration { + pub(crate) fn metadata_mut<'a>(&self) -> &'a mut IMetaDataImport2 { + get_mutex_value_mut( + &self.metadata + ) + } + + pub fn new(kind: DeclarationKind, metadata: Arc>, token: mdTypeDef) -> Self { let value = Self { kind, metadata, token, - _marker: marker::PhantomData, }; assert!(!value.metadata.is_null()); diff --git a/core/src/metadata/meta_data_reader.rs b/core/src/metadata/meta_data_reader.rs index 699cafb..629ef98 100644 --- a/core/src/metadata/meta_data_reader.rs +++ b/core/src/metadata/meta_data_reader.rs @@ -38,8 +38,8 @@ impl MetadataReader { ) ); } - let mut metadata = std::mem::MaybeUninit::uninit(); - let meta = &mut metadata; + let mut metadata = unsafe { std::mem::MaybeUninit::uninit() }; + let meta = &mut metadata.as_mut_ptr() as *mut *mut c_void; let mut token = mdTokenNil; let mut full_name_hstring = HSTRING::from(full_name); let get_metadata_file_result = rometadataresolution::ro_get_meta_data_file( @@ -60,19 +60,18 @@ impl MetadataReader { let mut flags = 0; let mut parent_token = mdTokenNil; debug_assert!(imeta_data_import2::get_type_def_props( - metadata, token, None, None, None, Some(&mut flags), Some(&mut parent_token), + metadata.as_mut_ptr(), token, None, None, None, Some(&mut flags), Some(&mut parent_token), ).is_ok()); if helpers::is_td_class(flags) { - let mut parent_name = vec![0_u16; MAX_IDENTIFIER_LENGTH]; - + let mut parent_name = [0_u16; MAX_IDENTIFIER_LENGTH]; match CorTokenType::from(enums::type_from_token(parent_token)) { CorTokenType::mdtTypeDef => { debug_assert!( imeta_data_import2::get_type_def_props( - metadata, parent_token, Some(parent_name.as_mut_ptr()), Some(parent_name.len() as u32), + metadata.as_mut_ptr(), parent_token, Some(parent_name.as_mut_ptr()), Some(parent_name.len() as u32), None, None, None, ).is_ok() ); @@ -80,7 +79,7 @@ impl MetadataReader { CorTokenType::mdtTypeRef => { debug_assert!( imeta_data_import2::get_type_ref_props( - metadata, parent_token, None, Some(parent_name.as_mut_ptr()), Some(parent_name.len() as u32), None, + metadata.as_mut_ptr(), parent_token, None, Some(parent_name.as_mut_ptr()), Some(parent_name.len() as u32), None, ).is_ok() ) } @@ -89,8 +88,14 @@ impl MetadataReader { } } - let mut parent_name_string = OsString::from_wide(parent_name.as_slice()).to_string_lossy().as_ref(); - + let mut parent_name_string = OsString::from_wide(&parent_name).to_string_lossy().as_ref(); + let metadata = unsafe { + Arc::new( + Mutex::new( + metadata.assume_init() + ) + ) + }; if parent_name_string == SYSTEM_ENUM { return Some( Arc::new( @@ -131,6 +136,13 @@ impl MetadataReader { } if helpers::is_td_interface(flags) { + let metadata = unsafe { + Arc::new( + Mutex::new( + metadata.assume_init() + ) + ) + }; return if full_name.contains("`") { Some( Arc::new( diff --git a/core/src/metadata/signature.rs b/core/src/metadata/signature.rs index d1d0f40..dffc864 100644 --- a/core/src/metadata/signature.rs +++ b/core/src/metadata/signature.rs @@ -67,7 +67,7 @@ impl Signature { } } - pub fn to_string<'a>(metadata: *mut c_void, signature: PCCOR_SIGNATURE) -> Cow<'a, str> { + pub fn to_string<'a>(metadata: *mut IMetaDataImport2, signature: PCCOR_SIGNATURE) -> Cow<'a, str> { let element_type = helpers::cor_sig_uncompress_element_type(signature); use crate::enums::CorElementType; return match element_type { diff --git a/core/src/prelude.rs b/core/src/prelude.rs index a3f643e..c0a90fc 100644 --- a/core/src/prelude.rs +++ b/core/src/prelude.rs @@ -35,6 +35,8 @@ pub const mdMethodSpecNil: mdToken = Helpers_mdMethodSpecNil; pub const mdStringNil: mdToken = Helpers_mdStringNil; pub use super::enums::*; +use std::sync::{Arc, Mutex}; + pub type CLSID = GUID; @@ -43,6 +45,21 @@ pub const RO_E_METADATA_NAME_IS_NAMESPACE: HRESULT = Helpers_RO_E_METADATA_NAME_ pub const MAX_IDENTIFIER_LENGTH: usize = 511; -pub const COR_CTOR_METHOD_NAME: &'static str = ".ctor"; -pub const COR_CCTOR_METHOD_NAME: &'static str = ".cctor"; -pub const COR_ENUM_FIELD_NAME: &'static str = "value__"; +pub const COR_CTOR_METHOD_NAME: &str = ".ctor"; +pub const COR_CCTOR_METHOD_NAME: &str = ".cctor"; +pub const COR_ENUM_FIELD_NAME: &str = "value__"; + + +pub fn get_mutex_value_mut<'a, T>(value: &Arc>) -> &mut T { + match value.lock() { + Ok(value) => &mut *value, + Err(poisoned) => &mut *poisoned.into_inner() + } +} + +pub fn get_mutex_value<'a, T>(value: &Arc>) -> &T { + match value.lock() { + Ok(value) => &*value, + Err(poisoned) => &*poisoned.into_inner() + } +} diff --git a/core/src/runtime/com/com_constructor.rs b/core/src/runtime/com/com_constructor.rs new file mode 100644 index 0000000..ac1d974 --- /dev/null +++ b/core/src/runtime/com/com_constructor.rs @@ -0,0 +1,2 @@ +#[derive(Debug)] +pub struct COMConstructor {} \ No newline at end of file diff --git a/core/src/runtime/com/com_interop.rs b/core/src/runtime/com/com_interop.rs new file mode 100644 index 0000000..eedd2c5 --- /dev/null +++ b/core/src/runtime/com/com_interop.rs @@ -0,0 +1,6 @@ +#[derive(Debug)] +pub struct COMInterop {} + +impl COMInterop { + pub fn resolve_type(type_name: &str) {} +} \ No newline at end of file diff --git a/core/src/runtime/com/com_method_call.rs b/core/src/runtime/com/com_method_call.rs new file mode 100644 index 0000000..9a80a62 --- /dev/null +++ b/core/src/runtime/com/com_method_call.rs @@ -0,0 +1,2 @@ +#[derive(Debug)] +pub struct COMMethodCall {} \ No newline at end of file diff --git a/core/src/runtime/com/com_object_wrapper.rs b/core/src/runtime/com/com_object_wrapper.rs new file mode 100644 index 0000000..44d390e --- /dev/null +++ b/core/src/runtime/com/com_object_wrapper.rs @@ -0,0 +1,2 @@ +#[derive(Debug)] +pub struct COMObjectWrapper {} \ No newline at end of file diff --git a/core/src/runtime/com/com_unknown_type.rs b/core/src/runtime/com/com_unknown_type.rs new file mode 100644 index 0000000..d7ec009 --- /dev/null +++ b/core/src/runtime/com/com_unknown_type.rs @@ -0,0 +1,2 @@ +#[derive(Debug)] +pub struct COMUnknownType {} \ No newline at end of file diff --git a/core/src/runtime/com/mod.rs b/core/src/runtime/com/mod.rs index e69de29..2b084b4 100644 --- a/core/src/runtime/com/mod.rs +++ b/core/src/runtime/com/mod.rs @@ -0,0 +1,5 @@ +pub mod com_interop; +pub mod com_constructor; +pub mod com_unknown_type; +pub mod com_method_call; +pub mod com_object_wrapper; \ No newline at end of file diff --git a/core/src/runtime/console.rs b/core/src/runtime/console.rs index 9623ae9..4d44ffc 100755 --- a/core/src/runtime/console.rs +++ b/core/src/runtime/console.rs @@ -22,7 +22,7 @@ pub(crate) fn handle_console_log(scope: &mut v8::HandleScope, args: v8::Function let string = CString::new(value).unwrap(); let mut written = 0_u32; unsafe { - Console::WriteConsoleA(handle, string.as_ptr() as *const c_void, length, &mut written, std::ptr::null()); + Console::WriteConsoleA(handle, string.as_ptr() as *const c_void, length, &mut written, std::ptr::null() as _); } } diff --git a/core/src/runtime/ffi/ff_boolean_type.rs b/core/src/runtime/ffi/ff_boolean_type.rs new file mode 100644 index 0000000..aa3e47d --- /dev/null +++ b/core/src/runtime/ffi/ff_boolean_type.rs @@ -0,0 +1,2 @@ +#[derive(Debug)] +pub struct FFIBooleanType {} \ No newline at end of file diff --git a/core/src/runtime/ffi/ffi_interop.rs b/core/src/runtime/ffi/ffi_interop.rs new file mode 100644 index 0000000..18332fb --- /dev/null +++ b/core/src/runtime/ffi/ffi_interop.rs @@ -0,0 +1 @@ +pub struct FFIInterop {} \ No newline at end of file diff --git a/core/src/runtime/ffi/ffi_number_type.rs b/core/src/runtime/ffi/ffi_number_type.rs new file mode 100644 index 0000000..10a87a4 --- /dev/null +++ b/core/src/runtime/ffi/ffi_number_type.rs @@ -0,0 +1,2 @@ +#[derive(Debug)] +pub struct FFINumberType {} \ No newline at end of file diff --git a/core/src/runtime/ffi/ffi_void_type.rs b/core/src/runtime/ffi/ffi_void_type.rs new file mode 100644 index 0000000..fc4d3ae --- /dev/null +++ b/core/src/runtime/ffi/ffi_void_type.rs @@ -0,0 +1,2 @@ +#[derive(Debug)] +pub struct FFIVoidType {} \ No newline at end of file diff --git a/core/src/runtime/ffi/mod.rs b/core/src/runtime/ffi/mod.rs index e69de29..202dfc0 100755 --- a/core/src/runtime/ffi/mod.rs +++ b/core/src/runtime/ffi/mod.rs @@ -0,0 +1,4 @@ +pub mod ffi_interop; +pub mod ff_boolean_type; +pub mod ffi_number_type; +pub mod ffi_void_type; \ No newline at end of file diff --git a/core/src/runtime/mod.rs b/core/src/runtime/mod.rs index 9fe94c2..132ebc3 100755 --- a/core/src/runtime/mod.rs +++ b/core/src/runtime/mod.rs @@ -10,6 +10,7 @@ use std::io::Read; use std::os::windows::prelude::*; use std::path::{Path, PathBuf}; use windows::HSTRING; +use crate::runtime::com::com_interop::COMInterop; pub struct Runtime { isolate: v8::OwnedIsolate, @@ -42,6 +43,8 @@ impl Runtime { let mut global_template = v8::ObjectTemplate::new_from_template(scope, global); + global_template.set_internal_field_count(0); + { { Runtime::init_performance(scope, &mut global_template); @@ -53,6 +56,7 @@ impl Runtime { let mut context = v8::Context::new_from_template(scope, global_template); + let mut local_scope = v8::ContextScope::new(scope, context); { @@ -102,13 +106,17 @@ impl Runtime { let result = result.to_string(&mut scope).unwrap(); } - fn handle_global(_scope: &mut v8::HandleScope, _args: v8::FunctionCallbackArguments, _retval: v8::ReturnValue) {} + fn handle_global(_scope: &mut v8::HandleScope, _args: v8::FunctionCallbackArguments, _retval: v8::ReturnValue) { + + } fn init_global(scope: &mut v8::ContextScope>, context: v8::Local) { let mut global = context.global(scope); let value = v8::String::new( scope, "global", ).unwrap().into(); global.define_own_property(scope, value, global.into(), v8::READ_ONLY); + let interop = COMInterop + global.set_internal_field(0, ) } fn init_console(scope: &mut v8::ContextScope>, context: v8::Local) { @@ -195,6 +203,10 @@ impl Runtime { let class_name = args.get(0).to_rust_string_lossy(scope); + let global = scope.get_current_context().global(scope); + let interop = global.get_internal_field(scope, 0); + + } } From bec7edb2674aef09233e39e1c141223cc692cd12 Mon Sep 17 00:00:00 2001 From: Osei Fortune Date: Mon, 28 Jun 2021 06:44:14 -0400 Subject: [PATCH 11/11] updates --- .idea/windows-runtime.iml | 3 + core/Cargo.toml | 6 +- core/src/bindings.rs | 976 ------------------ core/src/bindings/imeta_data_import2.rs | 608 +++++++++++ core/src/bindings/mod.rs | 937 +++++++++++++++++ core/src/enums.rs | 458 ++++---- core/src/lib.rs | 6 - core/src/metadata/com_helpers.rs | 240 +++-- core/src/metadata/declaration_factory.rs | 41 +- .../declarations/base_class_declaration.rs | 568 +++++----- .../declarations/class_declaration.rs | 285 ++--- core/src/metadata/declarations/declaration.rs | 59 +- .../generic_delegate_declaration.rs | 94 +- .../generic_delegate_instance_declaration.rs | 118 ++- .../declarations/delegate_declaration/mod.rs | 125 ++- .../metadata/declarations/enum_declaration.rs | 58 +- .../declarations/event_declaration.rs | 341 +++--- .../declarations/field_declaration.rs | 134 ++- .../generic_interface_declaration.rs | 125 +-- .../generic_interface_instance_declaration.rs | 156 +-- .../declarations/interface_declaration/mod.rs | 106 +- .../declarations/method_declaration.rs | 447 ++++---- .../declarations/namespace_declaration.rs | 188 ++-- .../declarations/parameter_declaration.rs | 102 +- .../declarations/property_declaration.rs | 367 ++++--- .../declarations/struct_declaration.rs | 119 ++- .../declarations/struct_field_declaration.rs | 106 +- .../metadata/declarations/type_declaration.rs | 192 ++-- .../declaring_interface_for_method.rs | 64 +- .../metadata/generic_instance_id_builder.rs | 324 +++--- core/src/metadata/meta_data_reader.rs | 61 +- core/src/metadata/signature.rs | 293 +++--- core/src/prelude.rs | 68 +- core/src/runtime/com/com_constructor.rs | 17 +- core/src/runtime/com/com_interop.rs | 20 +- core/src/runtime/ffi/ffi_interop.rs | 1 + core/src/runtime/mod.rs | 392 +++---- 37 files changed, 4774 insertions(+), 3431 deletions(-) delete mode 100644 core/src/bindings.rs create mode 100644 core/src/bindings/imeta_data_import2.rs create mode 100644 core/src/bindings/mod.rs diff --git a/.idea/windows-runtime.iml b/.idea/windows-runtime.iml index a179829..0f4b92c 100644 --- a/.idea/windows-runtime.iml +++ b/.idea/windows-runtime.iml @@ -19,6 +19,9 @@ + + + diff --git a/core/Cargo.toml b/core/Cargo.toml index 44d14a6..c5838a3 100755 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -9,9 +9,9 @@ crate-type = ["dylib"] [dependencies] -windows = "0.10.0" -rusty_v8 = "0.21.0" +windows = "0.13.0" +rusty_v8 = "0.23.0" core_bindings = { package = "core_bindings", path = "../core-bindings" } chrono = "0.4.19" -libc = "0.2.95" +libc = "0.2.97" lazy_static = "1.4.0" diff --git a/core/src/bindings.rs b/core/src/bindings.rs deleted file mode 100644 index 047d80b..0000000 --- a/core/src/bindings.rs +++ /dev/null @@ -1,976 +0,0 @@ -use crate::prelude::*; -use windows::Abi; - - -pub(crate) fn ro_resolve_namespace(name: &windows::HSTRING, - windows_meta_data_dir: Option<&windows::HSTRING>, - package_graph_dirs_count: DWORD, - package_graph_dirs: Option<&windows::HSTRING>, - meta_data_file_paths_count: Option<&mut DWORD>, - meta_data_file_paths: Option<&mut windows::HSTRING>, - sub_namespaces_count: &mut DWORD, - sub_namespaces: Option<&mut windows::HSTRING>, -) -> HRESULT { - unsafe { - let name = name.abi() as HSTRING; - let windows_meta_data_dir = match windows_meta_data_dir { - None => { - 0 as _ - } - Some(windows_meta_data_dir) => { - windows_meta_data_dir.abi() - } - } as HSTRING; - let mut package_graph_dirs = match package_graph_dirs { - None => { - 0 as _ - } - Some(package_graph_dirs) => { - package_graph_dirs.abi() - } - }; - - let package_graph_dirs: *const *mut HSTRING__ = &mut package_graph_dirs as _; - let mut meta_data_file_paths = match meta_data_file_paths { - None => { - 0 as _ - } - Some(meta_data_file_paths) => { - meta_data_file_paths.abi() - } - }; - - let mut meta_data_file_paths = &mut meta_data_file_paths; - let meta_data_file_paths: *mut *mut HSTRING = &mut meta_data_file_paths as _; - - - let mut sub_namespaces = match sub_namespaces { - None => { - 0 as _ - } - Some(sub_namespaces) => { - sub_namespaces.abi() - } - }; - - let mut sub_namespaces = &mut sub_namespaces; - let sub_namespaces: *mut *mut HSTRING = &mut sub_namespaces as _; - - core_bindings::RoResolveNamespace( - name, windows_meta_data_dir, package_graph_dirs_count, - package_graph_dirs, meta_data_file_paths_count.unwrap_or(0 as _), - meta_data_file_paths, sub_namespaces_count, sub_namespaces, - ) - } -} - -pub mod rometadataresolution { - use crate::prelude::*; - use windows::{HRESULT, HSTRING, Abi}; - - pub(crate) fn ro_get_meta_data_file( - name: &mut windows::HSTRING, meta_data_dispenser: Option<*mut c_void>, meta_data_file_path: Option<*mut c_void>, meta_data_import: Option<*mut *mut c_void>, type_def_token: Option<*mut u32>, - ) -> HRESULT { - unsafe { - windows::HRESULT(core_bindings::Rometadataresolution_RoGetMetaDataFile( - std::mem::transmute(name), meta_data_dispenser.unwrap_or(0 as _), meta_data_file_path.unwrap_or(0 as _), meta_data_import.unwrap_or(0 as _), type_def_token.unwrap_or(0 as _), - ) as u32) - } - } - - pub(crate) fn ro_parse_type_name( - type_name: &mut windows::HSTRING, - parts_count: &mut DWORD, - type_name_parts: &mut windows::HSTRING, - ) -> HRESULT { - let type_name = type_name.abi() as _; - let type_name_parts = type_name_parts.abi() as _; - unsafe { - HRESULT( - core_bindings::Rometadataresolution_RoParseTypeName( - type_name, - parts_count, - type_name_parts, - ) as u32 - ) - } - } - - - pub(crate) fn ro_get_parameterized_type_instance_iid( - name_element_count: UINT32, - name_elements: *mut PCWSTR, - fn_: ::core::option::Option< - unsafe extern "C" fn(name: PCWSTR, builder: *mut IRoSimpleMetaDataBuilder) -> i32, - >, - iid: *mut GUID, - p_extra: Option<*mut ROPARAMIIDHANDLE>, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::Rometadataresolution_RoGetParameterizedTypeInstanceIID( - name_element_count, - name_elements, - fn_, - iid, - p_extra.unwrap_or(0 as _), - ) as u32 - ) - } - } - - pub(crate) fn ro_locator( - fn_: ::core::option::Option< - unsafe extern "C" fn(name: PCWSTR, builder: *mut IRoSimpleMetaDataBuilder) -> i32, - >, - locator: *mut Locator, - ) { - unsafe { - core_bindings::Rometadataresolution_Ro_Locator(fn_, locator) - } - } -} - -pub mod imeta_data_import2 { - use crate::prelude::*; - use core_bindings::*; - use windows::HRESULT; - - pub(crate) fn get_type_def_props(metadata: *mut IMetaDataImport2, md_type_def: c_uint, sz_type_def: Option, cch_type_def: Option, pch_type_def: Option<*mut ULONG>, pdw_type_def_flags: Option<*mut ULONG>, md_token: Option<*mut ULONG32>) -> HRESULT { - unsafe { - HRESULT(core_bindings::IMetaDataImport2_GetTypeDefProps(metadata, md_type_def, sz_type_def.unwrap_or(0 as _), cch_type_def.unwrap_or(0), pch_type_def.unwrap_or(&mut 0), pdw_type_def_flags.unwrap_or(0 as _), md_token.unwrap_or(&mut 0)) as u32) - } - } - - fn get_type_def_props_name_size(metadata: *mut IMetaDataImport2, md_type_def: c_uint, pch_type_def: *mut ULONG) -> HRESULT { - unsafe { - HRESULT(core_bindings::IMetaDataImport2_GetTypeDefPropsNameSize(metadata, md_type_def, pch_type_def) as u32) - } - } - - pub(crate) fn get_field_props(metadata: *mut IMetaDataImport2, - mb: mdFieldDef, - p_class: Option<*mut mdTypeDef>, - sz_field: Option<*mut u16>, - cch_field: Option, - pch_field: Option<*mut ULONG>, - pdw_attr: Option<*mut DWORD>, - ppv_sig_blob: Option<*mut PCCOR_SIGNATURE>, - pcb_sig_blob: Option<*mut ULONG>, - pdw_cplus_type_flag: Option<*mut DWORD>, - pp_value: Option<*mut UVCP_CONSTANT>, - pcch_value: Option<*mut ULONG>) -> windows::HRESULT { - unsafe { - HRESULT(core_bindings::IMetaDataImport2_GetFieldProps(metadata, - mb, - p_class.unwrap_or(0 as _), - sz_field.unwrap_or(0 as _), - cch_field.unwrap_or_default(), - pch_field.unwrap_or(0 as _), - pdw_attr.unwrap_or(0 as _), - ppv_sig_blob.unwrap_or(0 as _), - pcb_sig_blob.unwrap_or(0 as _), - pdw_cplus_type_flag.unwrap_or(0 as _), - pp_value.unwrap_or(0 as _), - pcch_value.unwrap_or(0 as _)) as u32) - } - } - - pub(crate) fn get_property_props(metadata: *mut IMetaDataImport2, prop: mdProperty, p_class: Option<*mut mdTypeDef>, - sz_property: Option<*mut u16>, - cch_property: Option, - pch_property: Option<*mut ULONG>, - pdw_prop_flags: Option<*mut DWORD>, - ppv_sig: Option<*mut PCCOR_SIGNATURE>, - pb_sig: Option<*mut ULONG>, - pdw_cplus_type_flag: Option<*mut DWORD>, - pp_default_value: Option<*mut UVCP_CONSTANT>, - pcch_default_value: Option<*mut ULONG>, - pmd_setter: Option<*mut mdMethodDef>, - pmd_getter: Option<*mut mdMethodDef>, - rmd_other_method: Option<*mut mdMethodDef>, - c_max: Option, - pc_other_method: Option<*mut ULONG>) -> windows::HRESULT { - unsafe { - HRESULT(core_bindings::IMetaDataImport2_GetPropertyProps( - metadata, prop, - p_class.unwrap_or(0 as _), - sz_property.unwrap_or(0 as _), - cch_property.unwrap_or_default(), - pch_property.unwrap_or(0 as _), - pdw_prop_flags.unwrap_or(0 as _), - ppv_sig.unwrap_or(0 as _), - pb_sig.unwrap_or(0 as _), - pdw_cplus_type_flag.unwrap_or(0 as _), - pp_default_value.unwrap_or(0 as _), - pcch_default_value.unwrap_or(0 as _), - pmd_setter.unwrap_or(0 as _), - pmd_getter.unwrap_or(0 as _), - rmd_other_method.unwrap_or(0 as _), - c_max.unwrap_or_default(), - pc_other_method.unwrap_or(0 as _), - ) as u32) - } - } - - pub(crate) fn get_method_props(metadata: *mut IMetaDataImport2, - tk_method_def: mdMethodDef, - ptk_class: Option<*mut mdTypeDef>, - sz_method: Option<*mut u16>, - cch_method: Option, - pch_method: Option<*mut ULONG>, - pdw_attr: Option<*mut DWORD>, - ppv_sig_blob: Option<*mut PCCOR_SIGNATURE>, - pcb_sig_blob: Option<*mut ULONG>, - pul_code_rva: Option<*mut ULONG>, - pdw_impl_flags: Option<*mut DWORD>) -> windows::HRESULT { - unsafe { - HRESULT(core_bindings::IMetaDataImport2_GetMethodProps( - metadata, tk_method_def, - ptk_class.unwrap_or(0 as _), sz_method.unwrap_or(0 as _), - cch_method.unwrap_or_default(), pch_method.unwrap_or(0 as _), - pdw_attr.unwrap_or(0 as _), ppv_sig_blob.unwrap_or(0 as _), - pcb_sig_blob.unwrap_or(0 as _), pul_code_rva.unwrap_or(0 as _), - pdw_impl_flags.unwrap_or(0 as _), - ) as u32) - } - } - - - pub(crate) fn enum_params(metadata: *mut IMetaDataImport2, ph_enum: *mut HCORENUM, mb: mdMethodDef, r_params: *mut mdParamDef, c_max: ULONG, - pc_tokens: *mut ULONG) -> windows::HRESULT { - unsafe { HRESULT(core_bindings::IMetaDataImport2_EnumParams(metadata, ph_enum, mb, r_params, c_max, pc_tokens) as u32) } - } - - pub(crate) fn close_enum(metadata: *mut IMetaDataImport2, ph_enum: HCORENUM) { - unsafe { - core_bindings::IMetaDataImport2_CloseEnum(metadata, ph_enum) - } - } - - pub(crate) fn get_param_props(metadata: *mut IMetaDataImport2, tk: mdParamDef, - pmd: Option<*mut mdMethodDef>, - pul_sequence: Option<*mut ULONG>, - sz_name: Option<*mut u16>, - cch_name: Option, - pch_name: Option<*mut ULONG>, - pdw_attr: Option<*mut DWORD>, - pdw_cplus_type_flag: Option<*mut DWORD>, - pp_value: Option<*mut UVCP_CONSTANT>, - pcch_value: Option<*mut ULONG>) -> windows::HRESULT { - unsafe { - HRESULT( - core_bindings::IMetaDataImport2_GetParamProps(metadata, tk, - pmd.unwrap_or(0 as _), - pul_sequence.unwrap_or(0 as _), - sz_name.unwrap_or(0 as _), - cch_name.unwrap_or_default(), - pch_name.unwrap_or(0 as _), - pdw_attr.unwrap_or(0 as _), - pdw_cplus_type_flag.unwrap_or(0 as _), - pp_value.unwrap_or(0 as _), - pcch_value.unwrap_or(0 as _)) as u32 - ) - } - } - - pub(crate) fn get_custom_attribute_by_name(metadata: *mut IMetaDataImport2, - tk_obj: mdToken, - sz_name: Option<*const u16>, - pp_data: Option<*mut *const ::core::ffi::c_void>, - pcb_data: Option<*mut ULONG>) -> windows::HRESULT { - unsafe { - HRESULT(core_bindings::IMetaDataImport2_GetCustomAttributeByName(metadata, - tk_obj, - sz_name.unwrap_or(0 as _), - pp_data.unwrap_or(0 as _), - pcb_data.unwrap_or(0 as _)) as u32) - } - } - - pub(crate) fn enum_interface_impls(metadata: *mut IMetaDataImport2, ph_enum: *mut HCORENUM, - td: Option, - r_impls: Option<*mut mdInterfaceImpl>, - c_max: Option, - pc_impls: Option<*mut ULONG>) -> windows::HRESULT { - unsafe { - HRESULT(core_bindings::IMetaDataImport2_EnumInterfaceImpls(metadata, ph_enum, - td.unwrap_or_default(), - r_impls.unwrap_or(0 as _), - c_max.unwrap_or(0 as _), - pc_impls.unwrap_or(0 as _)) as u32) - } - } - - pub(crate) fn get_type_ref_props(metadata: *mut IMetaDataImport2, tr: mdTypeRef, - ptk_resolution_scope: Option<*mut mdToken>, - sz_name: Option<*mut u16>, - cch_name: Option, - pch_name: Option<*mut ULONG>) -> windows::HRESULT { - unsafe { - HRESULT( - core_bindings::IMetaDataImport2_GetTypeRefProps(metadata, tr, - ptk_resolution_scope.unwrap_or(0 as _), - sz_name.unwrap_or(0 as _), - cch_name.unwrap_or_default(), - pch_name.unwrap_or(0 as _)) as u32 - ) - } - } - - pub(crate) fn find_method(metadata: *mut IMetaDataImport2, - td: mdTypeDef, - sz_name: LPCWSTR, - pv_sig_blob: Option, - cb_sig_blob: Option, - pmb: Option<*mut mdMethodDef>) -> windows::HRESULT { - unsafe { - HRESULT( - IMetaDataImport2_FindMethod(metadata, td, sz_name, pv_sig_blob.unwrap_or(0 as _), cb_sig_blob.unwrap_or_default(), pmb.unwrap_or(0 as _)) as u32 - ) - } - } - - pub(crate) fn enum_generic_params( - metadata: *mut IMetaDataImport2, - ph_enum: *mut HCORENUM, - tk: mdToken, - r_generic_params: Option<*mut mdGenericParam>, - c_max: Option, - pc_generic_params: Option<*mut ULONG>, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::IMetaDataImport2_EnumGenericParams( - metadata, - ph_enum, - tk, - r_generic_params.unwrap_or(0 as _), - c_max.unwrap_or_default(), - pc_generic_params.unwrap_or(0 as _), - ) as u32 - ) - } - } - - - pub fn count_enum( - metadata: *mut IMetaDataImport2, - h_enum: HCORENUM, - pul_count: *mut ULONG, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::IMetaDataImport2_CountEnum(metadata, h_enum, pul_count) as u32 - ) - } - } - - pub fn get_type_spec_from_token( - metadata: *mut IMetaDataImport2, - typespec: mdTypeSpec, - ppv_sig: *mut PCCOR_SIGNATURE, - pcb_sig: *mut ULONG, - ) -> HRESULT { - unsafe { - HRESULT( - IMetaDataImport2_GetTypeSpecFromToken( - metadata, - typespec, - ppv_sig, - pcb_sig, - ) as u32 - ) - } - } - - - pub(crate) fn enum_fields( - metadata: *mut IMetaDataImport2, - ph_enum: *mut HCORENUM, - tk_type_def: mdTypeDef, - rg_fields: *mut mdFieldDef, - c_max: ULONG, - pc_tokens: *mut ULONG, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::IMetaDataImport2_EnumFields( - metadata, - ph_enum, - tk_type_def, - rg_fields, - c_max, - pc_tokens, - ) as u32 - ) - } - } - - pub(crate) fn enum_methods_with_name( - metadata: *mut IMetaDataImport2, - ph_enum: *mut HCORENUM, - tk_type_def: mdTypeDef, - sz_name: LPCWSTR, - rg_methods: *mut mdMethodDef, - c_max: ULONG, - pc_tokens: *mut ULONG, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::IMetaDataImport2_EnumMethodsWithName( - metadata, - ph_enum, - tk_type_def, - sz_name, - rg_methods, - c_max, - pc_tokens, - ) as u32 - ) - } - } - - pub(crate) fn get_interface_impl_props( - metadata: *mut IMetaDataImport2, - tk_interface_impl: mdInterfaceImpl, - ptk_class: Option<*mut mdTypeDef>, - ptk_iface: Option<*mut mdToken>, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::IMetaDataImport2_GetInterfaceImplProps( - metadata, - tk_interface_impl, - ptk_class.unwrap_or(0 as _), - ptk_iface.unwrap_or(0 as _), - ) as u32 - ) - } - } - - pub(crate) fn enum_methods( - metadata: *mut IMetaDataImport2, - ph_enum: *mut HCORENUM, - tk_type_def: mdTypeDef, - rg_methods: *mut mdMethodDef, - c_max: ULONG, - pc_tokens: *mut ULONG, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::IMetaDataImport2_EnumMethods( - metadata, - ph_enum, - tk_type_def, - rg_methods, - c_max, - pc_tokens, - ) as u32 - ) - } - } - - pub(crate) fn enum_properties( - metadata: *mut IMetaDataImport2, - ph_enum: *mut HCORENUM, - tk_typ_def: mdTypeDef, - rg_properties: *mut mdProperty, - c_max: ULONG, - pc_properties: *mut ULONG, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::IMetaDataImport2_EnumProperties( - metadata, - ph_enum, - tk_typ_def, - rg_properties, - c_max, - pc_properties, - ) as u32 - ) - } - } - - pub fn enum_events( - metadata: *mut IMetaDataImport2, - ph_enum: *mut HCORENUM, - tk_typ_def: mdTypeDef, - rg_events: *mut mdEvent, - c_max: ULONG, - pc_events: *mut ULONG, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::IMetaDataImport2_EnumEvents( - metadata, - ph_enum, - tk_typ_def, - rg_events, - c_max, - pc_events, - ) as u32 - ) - } - } - - pub(crate) fn get_event_props( - metadata: *mut IMetaDataImport2, - ev: mdEvent, - p_class: Option<*mut mdTypeDef>, - sz_event: Option, - cch_event: Option, - pch_event: Option<*mut ULONG>, - pdw_event_flags: Option<*mut DWORD>, - ptk_event_type: Option<*mut mdToken>, - pmd_add_on: Option<*mut mdMethodDef>, - pmd_remove_on: Option<*mut mdMethodDef>, - pmd_fire: Option<*mut mdMethodDef>, - rmd_other_method: Option<*mut mdMethodDef>, - c_max: Option, - pc_other_method: Option<*mut ULONG>, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::IMetaDataImport2_GetEventProps( - metadata, - ev, - p_class.unwrap_or(0 as _), - sz_event.unwrap_or(0 as _), - cch_event.unwrap_or_default(), - pch_event.unwrap_or(0 as _), - pdw_event_flags.unwrap_or(0 as _), - ptk_event_type.unwrap_or(0 as _), - pmd_add_on.unwrap_or(0 as _), - pmd_remove_on.unwrap_or(0 as _), - pmd_fire.unwrap_or(0 as _), - rmd_other_method.unwrap_or(0 as _), - c_max.unwrap_or_default(), - pc_other_method.unwrap_or(0 as _), - ) as u32 - ) - } - } - - - pub(crate) fn find_field( - metadata: *mut IMetaDataImport2, - td: mdTypeDef, - sz_name: Option, - pv_sig_blob: Option, - cb_sig_blob: Option, - pmb: Option<*mut mdFieldDef>, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::IMetaDataImport2_FindField( - metadata, - td, - sz_name.unwrap_or(0 as _), - pv_sig_blob.unwrap_or(0 as _), - cb_sig_blob.unwrap_or_default(), - pmb.unwrap_or(0 as _), - ) as u32 - ) - } - } - - pub(crate) fn get_member_ref_props( - metadata: *mut IMetaDataImport2, - tk_member_ref: mdMemberRef, - ptk: Option<*mut mdToken>, - sz_member: Option, - cch_member: Option, - pch_member: Option<*mut ULONG>, - ppv_sig_blob: Option<*mut PCCOR_SIGNATURE>, - pcb_sig_blob: Option<*mut ULONG>, - ) -> HRESULT { - unsafe { - HRESULT(core_bindings::IMetaDataImport2_GetMemberRefProps( - metadata, - tk_member_ref, - ptk.unwrap_or(0 as _), - sz_member.unwrap_or(0 as _), - cch_member.unwrap_or_default(), - pch_member.unwrap_or(0 as _), - ppv_sig_blob.unwrap_or(0 as _), - pcb_sig_blob.unwrap_or(0 as _), - ) as u32) - } - } - - pub fn get_custom_attribute_props( - metadata: *mut IMetaDataImport2, - cv: mdCustomAttribute, - ptk_obj: Option<*mut mdToken>, - ptk_type: Option<*mut mdToken>, - pp_blob: Option<*mut *const BYTE>, - pcb_blob: Option<*mut ULONG>, - ) -> HRESULT { - HRESULT::from_win32( - unsafe { - core_bindings::IMetaDataImport2_GetCustomAttributeProps( - metadata, - cv, - ptk_obj.unwrap_or(0 as _), - ptk_type.unwrap_or(0 as _), - pp_blob.unwrap_or(0 as _), - pcb_blob.unwrap_or(0 as _), - ) - } as u32 - ) - } - - pub fn enum_custom_attributes( - metadata: *mut IMetaDataImport2, - ph_enum: Option<*mut HCORENUM>, - tk: Option, - tk_type: Option, - rg_custom_attributes: Option<*mut mdCustomAttribute>, - c_max: Option, - pc_custom_attributes: Option<*mut ULONG>, - ) -> HRESULT { - unsafe { - HRESULT::from_win32( - core_bindings::IMetaDataImport2_EnumCustomAttributes( - metadata, - ph_enum.unwrap_or(0 as _), - tk.unwrap_or_default(), - tk_type.unwrap_or_default(), - rg_custom_attributes.unwrap_or(0 as _), - c_max.unwrap_or_default(), - pc_custom_attributes.unwrap_or(0 as _), - ) as u32 - ) - } - } - - pub(crate) fn find_type_def_by_name( - metadata: *mut IMetaDataImport2, - sz_type_def: Option, - tk_enclosing_class: Option, - ptk_type_def: Option<*mut mdTypeDef>, - ) -> HRESULT { - unsafe { - HRESULT::from_win32( - core_bindings::IMetaDataImport2_FindTypeDefByName( - metadata, - sz_type_def.unwrap_or(0 as _), - tk_enclosing_class.unwrap_or(0 as _), - ptk_type_def.unwrap_or(0 as _), - ) as u32 - ) - } - } - - pub fn enum_method_impls( - metadata: *mut IMetaDataImport2, - ph_enum: *mut HCORENUM, - tk_type_def: Option, - r_method_body: Option<&mut [mdToken]>, - r_method_decl: Option<&mut [mdToken]>, - c_max: Option, - pc_tokens: Option<&mut ULONG>, - ) -> HRESULT { - let r_method_body = if let Some(r_method_body) = r_method_body { - r_method_body.as_mut_ptr() - } else { - 0 as _ - }; - - let r_method_decl = if let Some(r_method_decl) = r_method_decl { - r_method_decl.as_mut_ptr() - } else { - 0 as _ - }; - - unsafe { - HRESULT::from_win32( - core_bindings::IMetaDataImport2_EnumMethodImpls( - metadata, - ph_enum, - tk_type_def.unwrap_or_default(), - r_method_body, - r_method_decl, - c_max.unwrap_or_default(), - pc_tokens.unwrap_or(0 as _), - ) as u32 - ) - } - } -} - -pub mod iro_simple_meta_data_builder { - use crate::prelude::*; - use windows::{HRESULT, HSTRING}; - - pub(crate) fn set_runtime_class_simple_default( - builder: *mut IRoSimpleMetaDataBuilder, - name: PCWSTR, - default_interface_name: PCWSTR, - default_interface_iid: *const GUID, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::IRoSimpleMetaDataBuilder_SetRuntimeClassSimpleDefault( - builder, - name, - default_interface_name, - default_interface_iid, - ) as u32 - ) - } - } - - - pub(crate) fn set_win_rt_interface( - builder: *mut IRoSimpleMetaDataBuilder, - iid: GUID, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::IRoSimpleMetaDataBuilder_SetWinRtInterface( - builder, - iid, - ) as u32 - ) - } - } - - - pub fn set_parameterized_interface( - builder: *mut IRoSimpleMetaDataBuilder, - piid: GUID, - num_args: UINT32, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::IRoSimpleMetaDataBuilder_SetParameterizedInterface( - builder, - piid, - num_args, - ) as u32 - ) - } - } - - - pub fn set_enum( - builder: *mut IRoSimpleMetaDataBuilder, - name: PCWSTR, - base_type: PCWSTR, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::IRoSimpleMetaDataBuilder_SetEnum( - builder, - name, - base_type, - ) as u32 - ) - } - } - - - pub fn set_struct( - builder: *mut IRoSimpleMetaDataBuilder, - name: PCWSTR, - num_fields: UINT32, - field_type_names: *const PCWSTR, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::IRoSimpleMetaDataBuilder_SetStruct( - builder, - name, - num_fields, - field_type_names, - ) as u32 - ) - } - } - - - pub fn set_delegate( - builder: *mut IRoSimpleMetaDataBuilder, - iid: GUID, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::IRoSimpleMetaDataBuilder_SetDelegate( - builder, - iid, - ) as u32 - ) - } - } - - - pub fn set_parameterized_delegate( - builder: *mut IRoSimpleMetaDataBuilder, - piid: GUID, - num_args: UINT32, - ) -> HRESULT { - unsafe { - HRESULT( - core_bindings::IRoSimpleMetaDataBuilder_SetParameterizedDelegate( - builder, - piid, - num_args, - ) as u32 - ) - } - } -} - -pub mod enums { - use crate::prelude::*; - - pub(crate) fn type_from_token(token: mdToken) -> ULONG { - unsafe { core_bindings::Enums_TypeFromToken(token) } - } -} - -pub mod helpers { - use crate::prelude::*; - use core_bindings::PCCOR_SIGNATURE; - use windows::HSTRING; - - pub(crate) fn get_type_name(metadata: *mut IMetaDataImport2, md_token: mdToken, name: *mut libc::wchar_t, size: ULONG) -> ULONG { - unsafe { core_bindings::Helpers_Get_Type_Name(metadata, md_token, name, size) } - } - - pub(crate) fn is_td_public(value: DWORD) -> bool { - unsafe { core_bindings::Helpers_IsTdPublic(value) == 1 } - } - - pub(crate) fn is_td_special_name(value: DWORD) -> bool { - unsafe { core_bindings::Helpers_IsTdSpecialName(value) == 1 } - } - - pub(crate) fn cor_sig_uncompress_calling_conv(p_data: PCCOR_SIGNATURE) -> ULONG { - unsafe { - core_bindings::Helpers_CorSigUncompressCallingConv(p_data) - } - } - - pub(crate) fn cor_sig_uncompress_data(p_data: PCCOR_SIGNATURE) -> ULONG { - unsafe { core_bindings::Helpers_CorSigUncompressData(p_data) } - } - - pub(crate) fn cor_sig_uncompress_element_type(p_data: PCCOR_SIGNATURE) -> crate::enums::CorElementType { - unsafe { - core_bindings::Helpers_CorSigUncompressElementType(p_data).into() - } - } - - pub(crate) fn cor_sig_uncompress_token(p_data: PCCOR_SIGNATURE) -> mdToken { - unsafe { - core_bindings::Helpers_CorSigUncompressToken(p_data) - } - } - - pub(crate) fn to_wstring(index: ULONG, text: *mut u16) -> usize { - unsafe { - core_bindings::Helpers_to_wstring(index, text) - } - } - - pub(crate) fn is_md_public(value: DWORD) -> bool { - unsafe { core_bindings::Helpers_IsMdPublic(value) == 1 } - } - - pub(crate) fn is_md_family(value: DWORD) -> bool { - unsafe { core_bindings::Helpers_IsMdFamily(value) == 1 } - } - - pub(crate) fn is_md_fam_orassem(value: DWORD) -> bool { - unsafe { core_bindings::Helpers_IsMdFamORAssem(value) == 1 } - } - - pub(crate) fn is_md_special_name(value: DWORD) -> bool { - unsafe { core_bindings::Helpers_IsMdSpecialName(value) == 1 } - } - - pub(crate) fn is_md_static(value: DWORD) -> bool { - unsafe { core_bindings::Helpers_IsMdStatic(value) == 1 } - } - - pub(crate) fn is_md_final(value: DWORD) -> bool { - unsafe { core_bindings::Helpers_IsMdFinal(value) == 1 } - } - - pub(crate) fn is_md_instance_initializer_w(flags: DWORD, name_data: *const u16) -> bool { - unsafe { - core_bindings::Helpers_IsMdInstanceInitializerW(flags, name_data) == 1 - } - } - - pub(crate) fn is_pr_special_name(value: DWORD) -> bool { - unsafe { - core_bindings::Helpers_IsPrSpecialName(value) == 1 - } - } - - pub(crate) fn bytes_to_guid( - data: *mut u8, - guid: *mut GUID, - ) { - unsafe { - core_bindings::Helpers_bytesToGuid(data, guid) - } - } - - pub(crate) fn windows_get_string_raw_buffer(mut string: HSTRING, length: Option<*mut UINT32>) -> PCWSTR { - unsafe { - core_bindings::Helpers_WindowsGetStringRawBuffer(std::mem::transmute(&mut string), length.unwrap_or(0 as _)) - } - } - - pub(crate) fn is_td_interface(value: DWORD) -> bool { - unsafe { - core_bindings::Helpers_IsTdInterface(value) == 1 - } - } - - pub(crate) fn is_td_class(value: DWORD) -> bool { - unsafe { - core_bindings::Helpers_IsTdClass(value) == 1 - } - } - - pub fn is_ev_special_name(value: DWORD) -> bool { - unsafe { - core_bindings::Helpers_IsEvSpecialName(value) == 1 - } - } - - pub(crate) fn generate_id_name( - name_parts_w: *mut PCWSTR, - declaration_full_name: *mut u16, - name_parts_count: *mut DWORD, - ) { - unsafe { - core_bindings::Helpers_generate_id_name( - name_parts_w, - declaration_full_name, - name_parts_count, - ) - } - } - - pub(crate) fn to_string_length(value: PCWSTR, count: *mut usize) { - unsafe { - core_bindings::Helpers_toString_length(value, count); - } - } - - - pub(crate) fn is_td_sealed(value: DWORD) -> bool { - unsafe { core_bindings::Helpers_IsTdSealed(value) == 1 } - } -} - - - diff --git a/core/src/bindings/imeta_data_import2.rs b/core/src/bindings/imeta_data_import2.rs new file mode 100644 index 0000000..a6bfa47 --- /dev/null +++ b/core/src/bindings/imeta_data_import2.rs @@ -0,0 +1,608 @@ +use crate::prelude::*; +use windows::HRESULT; +pub struct IMetaDataImport2(IMetaDataImport2_); + + +impl IMetaDataImport2 { + pub(crate) fn empty() -> Self { + Self(std::ptr::null_mut()) + } + pub(crate) fn inner(&self) -> &core_bindings::IMetaDataImport2 { + &self.0 + } + pub fn get_type_def_props( + &self, + md_type_def: c_uint, + sz_type_def: Option<&mut [u16]>, + cch_type_def: Option, + pch_type_def: Option<&mut ULONG>, + pdw_type_def_flags: Option<&mut ULONG>, + md_token: Option<&mut ULONG32>, + ) -> HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_GetTypeDefProps( + &self.0 as _, + md_type_def, + sz_type_def.unwrap_or_default().as_mut_ptr(), + cch_type_def.unwrap_or(0), + pch_type_def.unwrap_or(&mut 0), + pdw_type_def_flags.unwrap_or(0 as _), + md_token.unwrap_or(&mut 0), + ) as u32) + } + } + + pub fn get_type_def_props_name_size( + &self, + md_type_def: c_uint, + pch_type_def: &mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_GetTypeDefPropsNameSize( + &self.0 as _, + md_type_def, + pch_type_def, + ) as u32) + } + } + + pub fn get_field_props( + &self, + mb: mdFieldDef, + p_class: Option<&mut mdTypeDef>, + sz_field: Option<&mut [u16]>, + cch_field: Option, + pch_field: Option<&mut ULONG>, + pdw_attr: Option<&mut DWORD>, + ppv_sig_blob: Option<*mut PCCOR_SIGNATURE>, + pcb_sig_blob: Option<&mut ULONG>, + pdw_cplus_type_flag: Option<&mut DWORD>, + pp_value: Option<&mut UVCP_CONSTANT>, + pcch_value: Option<&mut ULONG>, + ) -> HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_GetFieldProps( + &self.0 as _, + mb, + p_class.unwrap_or(0 as _), + sz_field.unwrap_or_default().as_mut_ptr(), + cch_field.unwrap_or_default(), + pch_field.unwrap_or(0 as _), + pdw_attr.unwrap_or(0 as _), + ppv_sig_blob.unwrap_or(0 as _), + pcb_sig_blob.unwrap_or(0 as _), + pdw_cplus_type_flag.unwrap_or(0 as _), + pp_value.unwrap_or(0 as _), + pcch_value.unwrap_or(0 as _), + ) as u32) + } + } + + pub fn get_property_props( + &self, + prop: mdProperty, + p_class: Option<&mut mdTypeDef>, + sz_property: Option<&mut [u16]>, + cch_property: Option, + pch_property: Option<&mut ULONG>, + pdw_prop_flags: Option<*mut DWORD>, + ppv_sig: Option<*mut PCCOR_SIGNATURE>, + pb_sig: Option<&mut ULONG>, + pdw_cplus_type_flag: Option<&mut DWORD>, + pp_default_value: Option<*mut UVCP_CONSTANT>, + pcch_default_value: Option<*mut ULONG>, + pmd_setter: Option<&mut mdMethodDef>, + pmd_getter: Option<&mut mdMethodDef>, + rmd_other_method: Option<&mut [mdMethodDef]>, + c_max: Option, + pc_other_method: Option<*mut ULONG>, + ) -> HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_GetPropertyProps( + &self.0 as _, + prop, + p_class.unwrap_or(0 as _), + sz_property.unwrap_or_default().as_mut_ptr(), + cch_property.unwrap_or_default(), + pch_property.unwrap_or(0 as _), + pdw_prop_flags.unwrap_or(0 as _), + ppv_sig.unwrap_or(0 as _), + pb_sig.unwrap_or(0 as _), + pdw_cplus_type_flag.unwrap_or(0 as _), + pp_default_value.unwrap_or(0 as _), + pcch_default_value.unwrap_or(0 as _), + pmd_setter.unwrap_or(0 as _), + pmd_getter.unwrap_or(0 as _), + rmd_other_method.unwrap_or_default().as_mut_ptr(), + c_max.unwrap_or_default(), + pc_other_method.unwrap_or(0 as _), + ) as u32) + } + } + + pub fn get_method_props( + &self, + tk_method_def: mdMethodDef, + ptk_class: Option<&mut mdTypeDef>, + sz_method: Option<&mut [u16]>, + cch_method: Option, + pch_method: Option<&mut ULONG>, + pdw_attr: Option<&mut DWORD>, + ppv_sig_blob: Option<*mut PCCOR_SIGNATURE>, + pcb_sig_blob: Option<&mut ULONG>, + pul_code_rva: Option<&mut ULONG>, + pdw_impl_flags: Option<&mut DWORD>, + ) -> windows::HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_GetMethodProps( + &self.0 as _, + tk_method_def, + ptk_class.unwrap_or(0 as _), + sz_method.unwrap_or_default().as_mut_ptr(), + cch_method.unwrap_or_default(), + pch_method.unwrap_or(0 as _), + pdw_attr.unwrap_or(0 as _), + ppv_sig_blob.unwrap_or(0 as _), + pcb_sig_blob.unwrap_or(0 as _), + pul_code_rva.unwrap_or(0 as _), + pdw_impl_flags.unwrap_or(0 as _), + ) as u32) + } + } + + pub fn enum_params( + &self, + ph_enum: *mut HCORENUM, + mb: mdMethodDef, + r_params: &mut [mdParamDef], + c_max: ULONG, + pc_tokens: &mut ULONG, + ) -> windows::HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_EnumParams( + &self.0 as _, + ph_enum, + mb, + r_params.as_mut_ptr(), + c_max, + pc_tokens, + ) as u32) + } + } + + pub fn close_enum(&self, ph_enum: HCORENUM) { + unsafe { core_bindings::IMetaDataImport2_CloseEnum(&self.0 as _, ph_enum) } + } + + pub fn get_param_props( + &self, + tk: mdParamDef, + pmd: Option<&mut mdMethodDef>, + pul_sequence: Option<&mut ULONG>, + sz_name: Option<&mut [u16]>, + cch_name: Option, + pch_name: Option<&mut ULONG>, + pdw_attr: Option<&mut DWORD>, + pdw_cplus_type_flag: Option<&mut DWORD>, + pp_value: Option<*mut UVCP_CONSTANT>, + pcch_value: Option<&mut ULONG>, + ) -> windows::HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_GetParamProps( + self.0 as _, + tk, + pmd.unwrap_or(0 as _), + pul_sequence.unwrap_or(0 as _), + sz_name.unwrap_or_default().as_mut_ptr(), + cch_name.unwrap_or_default(), + pch_name.unwrap_or(0 as _), + pdw_attr.unwrap_or(0 as _), + pdw_cplus_type_flag.unwrap_or(0 as _), + pp_value.unwrap_or(0 as _), + pcch_value.unwrap_or(0 as _), + ) as u32) + } + } + + pub fn get_custom_attribute_by_name( + &self, + tk_obj: mdToken, + sz_name: Option<&[u16]>, + pp_data: Option<*mut *const ::core::ffi::c_void>, + pcb_data: Option<&mut ULONG>, + ) -> windows::HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_GetCustomAttributeByName( + &self.0 as _, + tk_obj, + sz_name.unwrap_or_default().as_ptr(), + pp_data.unwrap_or(0 as _), + pcb_data.unwrap_or(0 as _), + ) as u32) + } + } + + pub fn enum_interface_impls( + &self, + ph_enum: *mut HCORENUM, + td: Option, + r_impls: Option<&mut [mdInterfaceImpl]>, + c_max: Option, + pc_impls: Option<&mut ULONG>, + ) -> windows::HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_EnumInterfaceImpls( + &self.0 as _, + ph_enum, + td.unwrap_or_default(), + r_impls.unwrap_or_default().as_mut_ptr(), + c_max.unwrap_or(0 as _), + pc_impls.unwrap_or(0 as _), + ) as u32) + } + } + + pub fn get_type_ref_props( + &self, + tr: mdTypeRef, + ptk_resolution_scope: Option<&mut mdToken>, + sz_name: Option<&mut [u16]>, + cch_name: Option, + pch_name: Option<&mut ULONG>, + ) -> windows::HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_GetTypeRefProps( + &self.0 as _, + tr, + ptk_resolution_scope.unwrap_or(0 as _), + sz_name.unwrap_or_default().as_mut_ptr(), + cch_name.unwrap_or_default(), + pch_name.unwrap_or(0 as _), + ) as u32) + } + } + + pub fn find_method( + &self, + td: mdTypeDef, + sz_name: LPCWSTR, + pv_sig_blob: Option, + cb_sig_blob: Option, + pmb: Option<&mut mdMethodDef>, + ) -> windows::HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_FindMethod( + &self.0 as _, + td, + sz_name, + pv_sig_blob.unwrap_or(0 as _), + cb_sig_blob.unwrap_or_default(), + pmb.unwrap_or(0 as _), + ) as u32) + } + } + + pub fn enum_generic_params( + &self, + ph_enum: *mut HCORENUM, + tk: mdToken, + r_generic_params: Option<&mut [mdGenericParam]>, + c_max: Option, + pc_generic_params: Option<&mut ULONG>, + ) -> HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_EnumGenericParams( + &self.0 as _, + ph_enum, + tk, + r_generic_params.unwrap_or_default().as_mut_ptr(), + c_max.unwrap_or_default(), + pc_generic_params.unwrap_or(0 as _), + ) as u32) + } + } + + pub fn count_enum(&self, h_enum: HCORENUM, pul_count: *mut ULONG) -> HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_CountEnum( + &self.0 as _, + h_enum, + pul_count, + ) as u32) + } + } + + pub fn get_type_spec_from_token( + &self, + typespec: mdTypeSpec, + ppv_sig: *mut PCCOR_SIGNATURE, + pcb_sig: &mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_GetTypeSpecFromToken( + &self.0 as _, + typespec, + ppv_sig, + pcb_sig, + ) as u32) + } + } + + pub fn enum_fields( + &self, + ph_enum: *mut HCORENUM, + tk_type_def: mdTypeDef, + rg_fields: &mut [mdFieldDef], + c_max: ULONG, + pc_tokens: &mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_EnumFields( + &self.0 as _, + ph_enum, + tk_type_def, + rg_fields, + c_max, + pc_tokens, + ) as u32) + } + } + + pub fn enum_methods_with_name( + &self, + ph_enum: &mut HCORENUM, + tk_type_def: mdTypeDef, + sz_name: LPCWSTR, + rg_methods: &mut [mdMethodDef], + c_max: ULONG, + pc_tokens: &mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_EnumMethodsWithName( + &self.0 as _, + ph_enum, + tk_type_def, + sz_name, + rg_methods.as_mut_ptr(), + c_max, + pc_tokens, + ) as u32) + } + } + + pub fn get_interface_impl_props( + &self, + tk_interface_impl: mdInterfaceImpl, + ptk_class: Option<&mut mdTypeDef>, + ptk_iface: Option<&mut mdToken>, + ) -> HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_GetInterfaceImplProps( + &self.0 as _, + tk_interface_impl, + ptk_class.unwrap_or(0 as _), + ptk_iface.unwrap_or(0 as _), + ) as u32) + } + } + + pub fn enum_methods( + &self, + ph_enum: &mut HCORENUM, + tk_type_def: mdTypeDef, + rg_methods: &mut [mdMethodDef], + c_max: ULONG, + pc_tokens: &mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_EnumMethods( + &self.0 as _, + ph_enum, + tk_type_def, + rg_methods.as_mut_ptr(), + c_max, + pc_tokens, + ) as u32) + } + } + + pub fn enum_properties( + &self, + ph_enum: *mut HCORENUM, + tk_typ_def: mdTypeDef, + rg_properties: &mut [mdProperty], + c_max: ULONG, + pc_properties: &mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_EnumProperties( + &self.0 as _, + ph_enum, + tk_typ_def, + rg_properties, + c_max, + pc_properties, + ) as u32) + } + } + + pub fn enum_events( + &self, + ph_enum: *mut HCORENUM, + tk_typ_def: mdTypeDef, + rg_events: &mut [mdEvent], + c_max: ULONG, + pc_events: &mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_EnumEvents( + &self.0 as _, + ph_enum, + tk_typ_def, + rg_events, + c_max, + pc_events, + ) as u32) + } + } + + pub fn get_event_props( + &self, + ev: mdEvent, + p_class: Option<&mut mdTypeDef>, + sz_event: Option, + cch_event: Option, + pch_event: Option<&mut ULONG>, + pdw_event_flags: Option<&mut DWORD>, + ptk_event_type: Option<&mut mdToken>, + pmd_add_on: Option<&mut mdMethodDef>, + pmd_remove_on: Option<&mut mdMethodDef>, + pmd_fire: Option<&mut mdMethodDef>, + rmd_other_method: Option<&mut [mdMethodDef]>, + c_max: Option, + pc_other_method: Option<&mut ULONG>, + ) -> HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_GetEventProps( + &self.0 as _, + ev, + p_class.unwrap_or(0 as _), + sz_event.unwrap_or(0 as _), + cch_event.unwrap_or_default(), + pch_event.unwrap_or(0 as _), + pdw_event_flags.unwrap_or(0 as _), + ptk_event_type.unwrap_or(0 as _), + pmd_add_on.unwrap_or(0 as _), + pmd_remove_on.unwrap_or(0 as _), + pmd_fire.unwrap_or(0 as _), + rmd_other_method.unwrap_or_default().as_mut_ptr(), + c_max.unwrap_or_default(), + pc_other_method.unwrap_or(0 as _), + ) as u32) + } + } + + pub fn find_field( + &self, + td: mdTypeDef, + sz_name: Option, + pv_sig_blob: Option, + cb_sig_blob: Option, + pmb: Option<&mut mdFieldDef>, + ) -> HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_FindField( + &self.0 as _, + td, + sz_name.unwrap_or(0 as _), + pv_sig_blob.unwrap_or(0 as _), + cb_sig_blob.unwrap_or_default(), + pmb.unwrap_or(0 as _), + ) as u32) + } + } + + pub fn get_member_ref_props( + &self, + tk_member_ref: mdMemberRef, + ptk: Option<&mut mdToken>, + sz_member: Option, + cch_member: Option, + pch_member: Option<&mut ULONG>, + ppv_sig_blob: Option<*mut PCCOR_SIGNATURE>, + pcb_sig_blob: Option<&mut ULONG>, + ) -> HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_GetMemberRefProps( + &self.0 as _, + tk_member_ref, + ptk.unwrap_or(0 as _), + sz_member.unwrap_or(0 as _), + cch_member.unwrap_or_default(), + pch_member.unwrap_or(0 as _), + ppv_sig_blob.unwrap_or(0 as _), + pcb_sig_blob.unwrap_or(0 as _), + ) as u32) + } + } + + pub fn get_custom_attribute_props( + &self, + cv: mdCustomAttribute, + ptk_obj: Option<&mut mdToken>, + ptk_type: Option<&mut mdToken>, + pp_blob: Option<*mut *const BYTE>, + pcb_blob: Option<&mut ULONG>, + ) -> HRESULT { + HRESULT::from_win32(unsafe { + core_bindings::IMetaDataImport2_GetCustomAttributeProps( + &self.0 as _, + cv, + ptk_obj.unwrap_or(0 as _), + ptk_type.unwrap_or(0 as _), + pp_blob.unwrap_or(0 as _), + pcb_blob.unwrap_or(0 as _), + ) + } as u32) + } + + pub fn enum_custom_attributes( + &self, + ph_enum: Option<*mut HCORENUM>, + tk: Option, + tk_type: Option, + rg_custom_attributes: Option<&mut [mdCustomAttribute]>, + c_max: Option, + pc_custom_attributes: Option<*mut ULONG>, + ) -> HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_EnumCustomAttributes( + &self.0 as _, + ph_enum.unwrap_or(0 as _), + tk.unwrap_or_default(), + tk_type.unwrap_or_default(), + rg_custom_attributes.unwrap_or(0 as _), + c_max.unwrap_or_default(), + pc_custom_attributes.unwrap_or(0 as _), + ) as u32) + } + } + + pub fn find_type_def_by_name( + &self, + sz_type_def: Option, + tk_enclosing_class: Option, + ptk_type_def: Option<&mut mdTypeDef>, + ) -> HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_FindTypeDefByName( + &self.0 as _, + sz_type_def.unwrap_or(0 as _), + tk_enclosing_class.unwrap_or(0 as _), + ptk_type_def.unwrap_or(0 as _), + ) as u32) + } + } + + pub fn enum_method_impls( + &self, + ph_enum: *mut HCORENUM, + tk_type_def: Option, + r_method_body: Option<&mut [mdToken]>, + r_method_decl: Option<&mut [mdToken]>, + c_max: Option, + pc_tokens: Option<&mut ULONG>, + ) -> HRESULT { + unsafe { + HRESULT::from_win32(core_bindings::IMetaDataImport2_EnumMethodImpls( + &self.0 as _, + ph_enum, + tk_type_def.unwrap_or_default(), + r_method_body.unwrap_or_default().as_mut_ptr(), + r_method_decl.unwrap_or_default().as_mut_ptr(), + c_max.unwrap_or_default(), + pc_tokens.unwrap_or(0 as _), + ) as u32) + } + } +} diff --git a/core/src/bindings/mod.rs b/core/src/bindings/mod.rs new file mode 100644 index 0000000..deaebb1 --- /dev/null +++ b/core/src/bindings/mod.rs @@ -0,0 +1,937 @@ +pub mod imeta_data_import2; + +use crate::prelude::*; +use windows::Abi; + +pub(crate) fn ro_resolve_namespace( + name: &windows::HSTRING, + windows_meta_data_dir: Option<&windows::HSTRING>, + package_graph_dirs_count: DWORD, + package_graph_dirs: Option<&windows::HSTRING>, + meta_data_file_paths_count: Option<&mut DWORD>, + meta_data_file_paths: Option<&mut windows::HSTRING>, + sub_namespaces_count: &mut DWORD, + sub_namespaces: Option<&mut windows::HSTRING>, +) -> HRESULT { + unsafe { + let name = name.abi() as HSTRING; + let windows_meta_data_dir = match windows_meta_data_dir { + None => 0 as _, + Some(windows_meta_data_dir) => windows_meta_data_dir.abi(), + } as HSTRING; + let mut package_graph_dirs = match package_graph_dirs { + None => 0 as _, + Some(package_graph_dirs) => package_graph_dirs.abi(), + }; + + let package_graph_dirs: *const *mut HSTRING__ = &mut package_graph_dirs as _; + let mut meta_data_file_paths = match meta_data_file_paths { + None => 0 as _, + Some(meta_data_file_paths) => meta_data_file_paths.abi(), + }; + + let mut meta_data_file_paths = &mut meta_data_file_paths; + let meta_data_file_paths: *mut *mut HSTRING = &mut meta_data_file_paths as _; + + let mut sub_namespaces = match sub_namespaces { + None => 0 as _, + Some(sub_namespaces) => sub_namespaces.abi(), + }; + + let mut sub_namespaces = &mut sub_namespaces; + let sub_namespaces: *mut *mut HSTRING = &mut sub_namespaces as _; + + core_bindings::RoResolveNamespace( + name, + windows_meta_data_dir, + package_graph_dirs_count, + package_graph_dirs, + meta_data_file_paths_count.unwrap_or(0 as _), + meta_data_file_paths, + sub_namespaces_count, + sub_namespaces, + ) + } +} + +pub mod rometadataresolution { + use crate::prelude::*; + use windows::{Abi, HRESULT, HSTRING}; + + pub(crate) fn ro_get_meta_data_file( + name: &mut windows::HSTRING, + meta_data_dispenser: Option<*mut c_void>, + meta_data_file_path: Option<*mut c_void>, + meta_data_import: Option<*mut *mut IMetaDataImport2>, + type_def_token: Option<*mut u32>, + ) -> HRESULT { + unsafe { + windows::HRESULT(core_bindings::Rometadataresolution_RoGetMetaDataFile( + std::mem::transmute(name), + meta_data_dispenser.unwrap_or(0 as _), + meta_data_file_path.unwrap_or(0 as _), + meta_data_import.unwrap_or(0 as _) as _, + type_def_token.unwrap_or(0 as _), + ) as u32) + } + } + + pub(crate) fn ro_parse_type_name( + type_name: &mut windows::HSTRING, + parts_count: &mut DWORD, + type_name_parts: &mut windows::HSTRING, + ) -> HRESULT { + let type_name = type_name.abi() as _; + let type_name_parts = type_name_parts.abi() as _; + unsafe { + HRESULT(core_bindings::Rometadataresolution_RoParseTypeName( + type_name, + parts_count, + type_name_parts, + ) as u32) + } + } + + pub(crate) fn ro_get_parameterized_type_instance_iid( + name_element_count: UINT32, + name_elements: *mut PCWSTR, + fn_: ::core::option::Option< + unsafe extern "C" fn(name: PCWSTR, builder: *mut IRoSimpleMetaDataBuilder) -> i32, + >, + iid: *mut GUID, + p_extra: Option<*mut ROPARAMIIDHANDLE>, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::Rometadataresolution_RoGetParameterizedTypeInstanceIID( + name_element_count, + name_elements, + fn_, + iid, + p_extra.unwrap_or(0 as _), + ) as u32, + ) + } + } + + pub(crate) fn ro_locator( + fn_: ::core::option::Option< + unsafe extern "C" fn(name: PCWSTR, builder: *mut IRoSimpleMetaDataBuilder) -> i32, + >, + locator: *mut Locator, + ) { + unsafe { core_bindings::Rometadataresolution_Ro_Locator(fn_, locator) } + } +} + +/* + +pub mod imeta_data_import2 { + use crate::prelude::*; + use core_bindings::*; + use windows::HRESULT; + + pub(crate) fn get_type_def_props(metadata: &mut IMetaDataImport2, md_type_def: c_uint, sz_type_def: Option<&mut [u16]>, cch_type_def: Option, pch_type_def: Option<*mut ULONG>, pdw_type_def_flags: Option<*mut ULONG>, md_token: Option<*mut ULONG32>) -> HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_GetTypeDefProps(metadata, md_type_def, sz_type_def.unwrap_or_default().as_mut_ptr(), cch_type_def.unwrap_or(0), pch_type_def.unwrap_or(&mut 0), pdw_type_def_flags.unwrap_or(0 as _), md_token.unwrap_or(&mut 0)) as u32) + } + } + + fn get_type_def_props_name_size(metadata: *mut IMetaDataImport2, md_type_def: c_uint, pch_type_def: *mut ULONG) -> HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_GetTypeDefPropsNameSize(metadata, md_type_def, pch_type_def) as u32) + } + } + + pub(crate) fn get_field_props(metadata: *mut IMetaDataImport2, + mb: mdFieldDef, + p_class: Option<*mut mdTypeDef>, + sz_field: Option<*mut u16>, + cch_field: Option, + pch_field: Option<*mut ULONG>, + pdw_attr: Option<*mut DWORD>, + ppv_sig_blob: Option<*mut PCCOR_SIGNATURE>, + pcb_sig_blob: Option<*mut ULONG>, + pdw_cplus_type_flag: Option<*mut DWORD>, + pp_value: Option<*mut UVCP_CONSTANT>, + pcch_value: Option<*mut ULONG>) -> windows::HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_GetFieldProps(metadata, + mb, + p_class.unwrap_or(0 as _), + sz_field.unwrap_or(0 as _), + cch_field.unwrap_or_default(), + pch_field.unwrap_or(0 as _), + pdw_attr.unwrap_or(0 as _), + ppv_sig_blob.unwrap_or(0 as _), + pcb_sig_blob.unwrap_or(0 as _), + pdw_cplus_type_flag.unwrap_or(0 as _), + pp_value.unwrap_or(0 as _), + pcch_value.unwrap_or(0 as _)) as u32) + } + } + + pub(crate) fn get_property_props(metadata: *mut IMetaDataImport2, prop: mdProperty, p_class: Option<*mut mdTypeDef>, + sz_property: Option<*mut u16>, + cch_property: Option, + pch_property: Option<*mut ULONG>, + pdw_prop_flags: Option<*mut DWORD>, + ppv_sig: Option<*mut PCCOR_SIGNATURE>, + pb_sig: Option<*mut ULONG>, + pdw_cplus_type_flag: Option<*mut DWORD>, + pp_default_value: Option<*mut UVCP_CONSTANT>, + pcch_default_value: Option<*mut ULONG>, + pmd_setter: Option<*mut mdMethodDef>, + pmd_getter: Option<*mut mdMethodDef>, + rmd_other_method: Option<*mut mdMethodDef>, + c_max: Option, + pc_other_method: Option<*mut ULONG>) -> windows::HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_GetPropertyProps( + metadata, prop, + p_class.unwrap_or(0 as _), + sz_property.unwrap_or(0 as _), + cch_property.unwrap_or_default(), + pch_property.unwrap_or(0 as _), + pdw_prop_flags.unwrap_or(0 as _), + ppv_sig.unwrap_or(0 as _), + pb_sig.unwrap_or(0 as _), + pdw_cplus_type_flag.unwrap_or(0 as _), + pp_default_value.unwrap_or(0 as _), + pcch_default_value.unwrap_or(0 as _), + pmd_setter.unwrap_or(0 as _), + pmd_getter.unwrap_or(0 as _), + rmd_other_method.unwrap_or(0 as _), + c_max.unwrap_or_default(), + pc_other_method.unwrap_or(0 as _), + ) as u32) + } + } + + pub(crate) fn get_method_props(metadata: &mut IMetaDataImport2, + tk_method_def: mdMethodDef, + ptk_class: Option<&mut mdTypeDef>, + sz_method: Option<&mut [u16]>, + cch_method: Option, + pch_method: Option<&mut ULONG>, + pdw_attr: Option<&mut DWORD>, + ppv_sig_blob: Option<*mut PCCOR_SIGNATURE>, + pcb_sig_blob: Option<&mut ULONG>, + pul_code_rva: Option<&mut ULONG>, + pdw_impl_flags: Option<&mut DWORD>) -> windows::HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_GetMethodProps( + metadata, tk_method_def, + ptk_class.unwrap_or(0 as _), sz_method.unwrap_or(0 as _), + cch_method.unwrap_or_default(), pch_method.unwrap_or(0 as _), + pdw_attr.unwrap_or(0 as _), ppv_sig_blob.unwrap_or(0 as _), + pcb_sig_blob.unwrap_or(0 as _), pul_code_rva.unwrap_or(0 as _), + pdw_impl_flags.unwrap_or(0 as _), + ) as u32) + } + } + + + pub(crate) fn enum_params(metadata: *mut IMetaDataImport2, ph_enum: *mut HCORENUM, mb: mdMethodDef, r_params: *mut mdParamDef, c_max: ULONG, + pc_tokens: *mut ULONG) -> windows::HRESULT { + unsafe { HRESULT(core_bindings::IMetaDataImport2_EnumParams(metadata, ph_enum, mb, r_params, c_max, pc_tokens) as u32) } + } + + pub(crate) fn close_enum(metadata: &mut IMetaDataImport2, ph_enum: HCORENUM) { + unsafe { + core_bindings::IMetaDataImport2_CloseEnum(metadata, ph_enum) + } + } + + pub(crate) fn get_param_props(metadata: *mut IMetaDataImport2, tk: mdParamDef, + pmd: Option<*mut mdMethodDef>, + pul_sequence: Option<*mut ULONG>, + sz_name: Option<*mut u16>, + cch_name: Option, + pch_name: Option<*mut ULONG>, + pdw_attr: Option<*mut DWORD>, + pdw_cplus_type_flag: Option<*mut DWORD>, + pp_value: Option<*mut UVCP_CONSTANT>, + pcch_value: Option<*mut ULONG>) -> windows::HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_GetParamProps(metadata, tk, + pmd.unwrap_or(0 as _), + pul_sequence.unwrap_or(0 as _), + sz_name.unwrap_or(0 as _), + cch_name.unwrap_or_default(), + pch_name.unwrap_or(0 as _), + pdw_attr.unwrap_or(0 as _), + pdw_cplus_type_flag.unwrap_or(0 as _), + pp_value.unwrap_or(0 as _), + pcch_value.unwrap_or(0 as _)) as u32 + ) + } + } + + pub(crate) fn get_custom_attribute_by_name(metadata: &mut IMetaDataImport2, + tk_obj: mdToken, + sz_name: Option<&[u16]>, + pp_data: Option<*mut *const ::core::ffi::c_void>, + pcb_data: Option<&mut ULONG>) -> windows::HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_GetCustomAttributeByName(metadata, + tk_obj, + sz_name.unwrap_or_default().as_ptr(), + pp_data.unwrap_or(0 as _), + pcb_data.unwrap_or(0 as _)) as u32) + } + } + + pub(crate) fn enum_interface_impls(metadata: *mut IMetaDataImport2, ph_enum: *mut HCORENUM, + td: Option, + r_impls: Option<*mut mdInterfaceImpl>, + c_max: Option, + pc_impls: Option<*mut ULONG>) -> windows::HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_EnumInterfaceImpls(metadata, ph_enum, + td.unwrap_or_default(), + r_impls.unwrap_or(0 as _), + c_max.unwrap_or(0 as _), + pc_impls.unwrap_or(0 as _)) as u32) + } + } + + pub(crate) fn get_type_ref_props(metadata: &mut IMetaDataImport2, + tr: mdTypeRef, + ptk_resolution_scope: Option<*mut mdToken>, + sz_name: Option<&mut [u16]>, + cch_name: Option, + pch_name: Option<*mut ULONG>) -> windows::HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_GetTypeRefProps(metadata, tr, + ptk_resolution_scope.unwrap_or(0 as _), + sz_name.unwrap_or_default().as_mut_ptr(), + cch_name.unwrap_or_default(), + pch_name.unwrap_or(0 as _)) as u32 + ) + } + } + + pub(crate) fn find_method(metadata: *mut IMetaDataImport2, + td: mdTypeDef, + sz_name: LPCWSTR, + pv_sig_blob: Option, + cb_sig_blob: Option, + pmb: Option<*mut mdMethodDef>) -> windows::HRESULT { + unsafe { + HRESULT( + IMetaDataImport2_FindMethod(metadata, td, sz_name, pv_sig_blob.unwrap_or(0 as _), cb_sig_blob.unwrap_or_default(), pmb.unwrap_or(0 as _)) as u32 + ) + } + } + + pub(crate) fn enum_generic_params( + metadata: *mut IMetaDataImport2, + ph_enum: *mut HCORENUM, + tk: mdToken, + r_generic_params: Option<*mut mdGenericParam>, + c_max: Option, + pc_generic_params: Option<*mut ULONG>, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_EnumGenericParams( + metadata, + ph_enum, + tk, + r_generic_params.unwrap_or(0 as _), + c_max.unwrap_or_default(), + pc_generic_params.unwrap_or(0 as _), + ) as u32 + ) + } + } + + + pub fn count_enum( + metadata: *mut IMetaDataImport2, + h_enum: HCORENUM, + pul_count: *mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_CountEnum(metadata, h_enum, pul_count) as u32 + ) + } + } + + pub fn get_type_spec_from_token( + metadata: *mut IMetaDataImport2, + typespec: mdTypeSpec, + ppv_sig: *mut PCCOR_SIGNATURE, + pcb_sig: *mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT( + IMetaDataImport2_GetTypeSpecFromToken( + metadata, + typespec, + ppv_sig, + pcb_sig, + ) as u32 + ) + } + } + + + pub(crate) fn enum_fields( + metadata: *mut IMetaDataImport2, + ph_enum: *mut HCORENUM, + tk_type_def: mdTypeDef, + rg_fields: *mut mdFieldDef, + c_max: ULONG, + pc_tokens: *mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_EnumFields( + metadata, + ph_enum, + tk_type_def, + rg_fields, + c_max, + pc_tokens, + ) as u32 + ) + } + } + + pub(crate) fn enum_methods_with_name( + metadata: &mut IMetaDataImport2, + ph_enum: &mut HCORENUM, + tk_type_def: mdTypeDef, + sz_name: LPCWSTR, + rg_methods: &mut [mdMethodDef], + c_max: ULONG, + pc_tokens: &mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_EnumMethodsWithName( + metadata, + ph_enum, + tk_type_def, + sz_name, + rg_methods.as_mut_ptr(), + c_max, + pc_tokens, + ) as u32 + ) + } + } + + pub(crate) fn get_interface_impl_props( + metadata: *mut IMetaDataImport2, + tk_interface_impl: mdInterfaceImpl, + ptk_class: Option<*mut mdTypeDef>, + ptk_iface: Option<*mut mdToken>, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_GetInterfaceImplProps( + metadata, + tk_interface_impl, + ptk_class.unwrap_or(0 as _), + ptk_iface.unwrap_or(0 as _), + ) as u32 + ) + } + } + + pub(crate) fn enum_methods( + metadata: &mut IMetaDataImport2, + ph_enum: &mut HCORENUM, + tk_type_def: mdTypeDef, + rg_methods: &mut [mdMethodDef], + c_max: ULONG, + pc_tokens: &mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_EnumMethods( + metadata, + ph_enum, + tk_type_def, + rg_methods.as_mut_ptr(), + c_max, + pc_tokens, + ) as u32 + ) + } + } + + pub(crate) fn enum_properties( + metadata: *mut IMetaDataImport2, + ph_enum: *mut HCORENUM, + tk_typ_def: mdTypeDef, + rg_properties: *mut mdProperty, + c_max: ULONG, + pc_properties: *mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_EnumProperties( + metadata, + ph_enum, + tk_typ_def, + rg_properties, + c_max, + pc_properties, + ) as u32 + ) + } + } + + pub fn enum_events( + metadata: *mut IMetaDataImport2, + ph_enum: *mut HCORENUM, + tk_typ_def: mdTypeDef, + rg_events: *mut mdEvent, + c_max: ULONG, + pc_events: *mut ULONG, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_EnumEvents( + metadata, + ph_enum, + tk_typ_def, + rg_events, + c_max, + pc_events, + ) as u32 + ) + } + } + + pub(crate) fn get_event_props( + metadata: *mut IMetaDataImport2, + ev: mdEvent, + p_class: Option<*mut mdTypeDef>, + sz_event: Option, + cch_event: Option, + pch_event: Option<*mut ULONG>, + pdw_event_flags: Option<*mut DWORD>, + ptk_event_type: Option<*mut mdToken>, + pmd_add_on: Option<*mut mdMethodDef>, + pmd_remove_on: Option<*mut mdMethodDef>, + pmd_fire: Option<*mut mdMethodDef>, + rmd_other_method: Option<*mut mdMethodDef>, + c_max: Option, + pc_other_method: Option<*mut ULONG>, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_GetEventProps( + metadata, + ev, + p_class.unwrap_or(0 as _), + sz_event.unwrap_or(0 as _), + cch_event.unwrap_or_default(), + pch_event.unwrap_or(0 as _), + pdw_event_flags.unwrap_or(0 as _), + ptk_event_type.unwrap_or(0 as _), + pmd_add_on.unwrap_or(0 as _), + pmd_remove_on.unwrap_or(0 as _), + pmd_fire.unwrap_or(0 as _), + rmd_other_method.unwrap_or(0 as _), + c_max.unwrap_or_default(), + pc_other_method.unwrap_or(0 as _), + ) as u32 + ) + } + } + + + pub(crate) fn find_field( + metadata: *mut IMetaDataImport2, + td: mdTypeDef, + sz_name: Option, + pv_sig_blob: Option, + cb_sig_blob: Option, + pmb: Option<*mut mdFieldDef>, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IMetaDataImport2_FindField( + metadata, + td, + sz_name.unwrap_or(0 as _), + pv_sig_blob.unwrap_or(0 as _), + cb_sig_blob.unwrap_or_default(), + pmb.unwrap_or(0 as _), + ) as u32 + ) + } + } + + pub(crate) fn get_member_ref_props( + metadata: *mut IMetaDataImport2, + tk_member_ref: mdMemberRef, + ptk: Option<*mut mdToken>, + sz_member: Option, + cch_member: Option, + pch_member: Option<*mut ULONG>, + ppv_sig_blob: Option<*mut PCCOR_SIGNATURE>, + pcb_sig_blob: Option<*mut ULONG>, + ) -> HRESULT { + unsafe { + HRESULT(core_bindings::IMetaDataImport2_GetMemberRefProps( + metadata, + tk_member_ref, + ptk.unwrap_or(0 as _), + sz_member.unwrap_or(0 as _), + cch_member.unwrap_or_default(), + pch_member.unwrap_or(0 as _), + ppv_sig_blob.unwrap_or(0 as _), + pcb_sig_blob.unwrap_or(0 as _), + ) as u32) + } + } + + pub fn get_custom_attribute_props( + metadata: *mut IMetaDataImport2, + cv: mdCustomAttribute, + ptk_obj: Option<*mut mdToken>, + ptk_type: Option<*mut mdToken>, + pp_blob: Option<*mut *const BYTE>, + pcb_blob: Option<*mut ULONG>, + ) -> HRESULT { + HRESULT::from_win32( + unsafe { + core_bindings::IMetaDataImport2_GetCustomAttributeProps( + metadata, + cv, + ptk_obj.unwrap_or(0 as _), + ptk_type.unwrap_or(0 as _), + pp_blob.unwrap_or(0 as _), + pcb_blob.unwrap_or(0 as _), + ) + } as u32 + ) + } + + pub fn enum_custom_attributes( + metadata: *mut IMetaDataImport2, + ph_enum: Option<*mut HCORENUM>, + tk: Option, + tk_type: Option, + rg_custom_attributes: Option<*mut mdCustomAttribute>, + c_max: Option, + pc_custom_attributes: Option<*mut ULONG>, + ) -> HRESULT { + unsafe { + HRESULT::from_win32( + core_bindings::IMetaDataImport2_EnumCustomAttributes( + metadata, + ph_enum.unwrap_or(0 as _), + tk.unwrap_or_default(), + tk_type.unwrap_or_default(), + rg_custom_attributes.unwrap_or(0 as _), + c_max.unwrap_or_default(), + pc_custom_attributes.unwrap_or(0 as _), + ) as u32 + ) + } + } + + pub(crate) fn find_type_def_by_name( + metadata: *mut IMetaDataImport2, + sz_type_def: Option, + tk_enclosing_class: Option, + ptk_type_def: Option<*mut mdTypeDef>, + ) -> HRESULT { + unsafe { + HRESULT::from_win32( + core_bindings::IMetaDataImport2_FindTypeDefByName( + metadata, + sz_type_def.unwrap_or(0 as _), + tk_enclosing_class.unwrap_or(0 as _), + ptk_type_def.unwrap_or(0 as _), + ) as u32 + ) + } + } + + pub fn enum_method_impls( + metadata: *mut IMetaDataImport2, + ph_enum: *mut HCORENUM, + tk_type_def: Option, + r_method_body: Option<&mut [mdToken]>, + r_method_decl: Option<&mut [mdToken]>, + c_max: Option, + pc_tokens: Option<&mut ULONG>, + ) -> HRESULT { + let r_method_body = if let Some(r_method_body) = r_method_body { + r_method_body.as_mut_ptr() + } else { + 0 as _ + }; + + let r_method_decl = if let Some(r_method_decl) = r_method_decl { + r_method_decl.as_mut_ptr() + } else { + 0 as _ + }; + + unsafe { + HRESULT::from_win32( + core_bindings::IMetaDataImport2_EnumMethodImpls( + metadata, + ph_enum, + tk_type_def.unwrap_or_default(), + r_method_body, + r_method_decl, + c_max.unwrap_or_default(), + pc_tokens.unwrap_or(0 as _), + ) as u32 + ) + } + } +} + +*/ + +pub mod iro_simple_meta_data_builder { + use crate::prelude::*; + use windows::{HRESULT, HSTRING}; + + pub(crate) fn set_runtime_class_simple_default( + builder: *mut IRoSimpleMetaDataBuilder, + name: PCWSTR, + default_interface_name: PCWSTR, + default_interface_iid: *const GUID, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IRoSimpleMetaDataBuilder_SetRuntimeClassSimpleDefault( + builder, + name, + default_interface_name, + default_interface_iid, + ) as u32, + ) + } + } + + pub(crate) fn set_win_rt_interface( + builder: *mut IRoSimpleMetaDataBuilder, + iid: GUID, + ) -> HRESULT { + unsafe { + HRESULT(core_bindings::IRoSimpleMetaDataBuilder_SetWinRtInterface(builder, iid) as u32) + } + } + + pub fn set_parameterized_interface( + builder: *mut IRoSimpleMetaDataBuilder, + piid: GUID, + num_args: UINT32, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IRoSimpleMetaDataBuilder_SetParameterizedInterface( + builder, piid, num_args, + ) as u32, + ) + } + } + + pub fn set_enum( + builder: *mut IRoSimpleMetaDataBuilder, + name: PCWSTR, + base_type: PCWSTR, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IRoSimpleMetaDataBuilder_SetEnum(builder, name, base_type) as u32, + ) + } + } + + pub fn set_struct( + builder: *mut IRoSimpleMetaDataBuilder, + name: PCWSTR, + num_fields: UINT32, + field_type_names: *const PCWSTR, + ) -> HRESULT { + unsafe { + HRESULT(core_bindings::IRoSimpleMetaDataBuilder_SetStruct( + builder, + name, + num_fields, + field_type_names, + ) as u32) + } + } + + pub fn set_delegate(builder: *mut IRoSimpleMetaDataBuilder, iid: GUID) -> HRESULT { + unsafe { HRESULT(core_bindings::IRoSimpleMetaDataBuilder_SetDelegate(builder, iid) as u32) } + } + + pub fn set_parameterized_delegate( + builder: *mut IRoSimpleMetaDataBuilder, + piid: GUID, + num_args: UINT32, + ) -> HRESULT { + unsafe { + HRESULT( + core_bindings::IRoSimpleMetaDataBuilder_SetParameterizedDelegate( + builder, piid, num_args, + ) as u32, + ) + } + } +} + +pub mod enums { + use crate::prelude::*; + + pub(crate) fn type_from_token(token: mdToken) -> ULONG { + unsafe { core_bindings::Enums_TypeFromToken(token) } + } +} + +pub mod helpers { + use crate::prelude::*; + use core_bindings::PCCOR_SIGNATURE; + use windows::HSTRING; + + pub(crate) fn get_type_name( + metadata: &IMetaDataImport2, + md_token: mdToken, + name: &mut [u16], + ) -> ULONG { + unsafe { + core_bindings::Helpers_Get_Type_Name( + metadata.inner() as _, + md_token, + name.as_mut_ptr(), + name.len(), + ) + } + } + + pub(crate) fn is_td_public(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsTdPublic(value) == 1 } + } + + pub(crate) fn is_td_special_name(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsTdSpecialName(value) == 1 } + } + + pub(crate) fn cor_sig_uncompress_calling_conv(p_data: PCCOR_SIGNATURE) -> ULONG { + unsafe { core_bindings::Helpers_CorSigUncompressCallingConv(p_data) } + } + + pub(crate) fn cor_sig_uncompress_data(p_data: PCCOR_SIGNATURE) -> ULONG { + unsafe { core_bindings::Helpers_CorSigUncompressData(p_data) } + } + + pub(crate) fn cor_sig_uncompress_element_type( + p_data: PCCOR_SIGNATURE, + ) -> crate::enums::CorElementType { + unsafe { core_bindings::Helpers_CorSigUncompressElementType(p_data).into() } + } + + pub(crate) fn cor_sig_uncompress_token(p_data: PCCOR_SIGNATURE) -> mdToken { + unsafe { core_bindings::Helpers_CorSigUncompressToken(p_data) } + } + + pub(crate) fn to_wstring(index: ULONG, text: &mut [u16]) -> usize { + unsafe { core_bindings::Helpers_to_wstring(index, text.as_mut_ptr()) } + } + + pub(crate) fn is_md_public(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsMdPublic(value) == 1 } + } + + pub(crate) fn is_md_family(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsMdFamily(value) == 1 } + } + + pub(crate) fn is_md_fam_orassem(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsMdFamORAssem(value) == 1 } + } + + pub(crate) fn is_md_special_name(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsMdSpecialName(value) == 1 } + } + + pub(crate) fn is_md_static(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsMdStatic(value) == 1 } + } + + pub(crate) fn is_md_final(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsMdFinal(value) == 1 } + } + + pub(crate) fn is_md_instance_initializer_w(flags: DWORD, name_data: *const u16) -> bool { + unsafe { core_bindings::Helpers_IsMdInstanceInitializerW(flags, name_data) == 1 } + } + + pub(crate) fn is_pr_special_name(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsPrSpecialName(value) == 1 } + } + + pub(crate) fn bytes_to_guid(data: *mut u8, guid: *mut GUID) { + unsafe { core_bindings::Helpers_bytesToGuid(data, guid) } + } + + pub(crate) fn windows_get_string_raw_buffer( + mut string: HSTRING, + length: Option<*mut UINT32>, + ) -> PCWSTR { + unsafe { + core_bindings::Helpers_WindowsGetStringRawBuffer( + std::mem::transmute(&mut string), + length.unwrap_or(0 as _), + ) + } + } + + pub(crate) fn is_td_interface(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsTdInterface(value) == 1 } + } + + pub(crate) fn is_td_class(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsTdClass(value) == 1 } + } + + pub fn is_ev_special_name(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsEvSpecialName(value) == 1 } + } + + pub(crate) fn generate_id_name(declaration_full_name: &str) -> ([u16], usize) { + let mut declaration_full_name = windows::HSTRING::from(declaration_full_name); + let mut declaration_full_name = declaration_full_name.as_wide(); + let mut name_parts = [0_u16; MAX_IDENTIFIER_LENGTH]; + let mut name_parts_count = 0; + let mut name_parts_w = &mut name_parts.as_ptr(); + unsafe { + core_bindings::Helpers_generate_id_name( + name_parts_w as _, + declaration_full_name.as_ptr() as _, + &mut name_parts_count, + ) + } + (*name_parts, name_parts_count) + } + + pub(crate) fn to_string_length(value: PCWSTR, count: *mut usize) { + unsafe { + core_bindings::Helpers_toString_length(value, count); + } + } + + pub(crate) fn is_td_sealed(value: DWORD) -> bool { + unsafe { core_bindings::Helpers_IsTdSealed(value) == 1 } + } +} diff --git a/core/src/enums.rs b/core/src/enums.rs index 13f0eba..51c6182 100644 --- a/core/src/enums.rs +++ b/core/src/enums.rs @@ -2,213 +2,291 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] +#[repr(C)] +#[derive(Copy, Clone, Debug)] +pub enum Initialization { + Activation, + Composition, +} #[derive(Copy, Clone, PartialEq, Debug)] #[repr(C)] -pub enum CorCallingConvention -{ - ImageCeeCsCallconvDefault = 0x0, - - ImageCeeCsCallconvVararg = 0x5, - ImageCeeCsCallconvField = 0x6, - ImageCeeCsCallconvLocalSig = 0x7, - ImageCeeCsCallconvProperty = 0x8, - ImageCeeCsCallconvUnmgd = 0x9, - ImageCeeCsCallconvGenericinst = 0xa, - // generic method instantiation - ImageCeeCsCallconvNativevararg = 0xb, - // used ONLY for 64bit vararg PInvoke calls - ImageCeeCsCallconvMax = 0xc, // first invalid calling convention - - - // The high bits of the calling convention convey additional info - ImageCeeCsCallconvMask = 0x0f, - // Calling convention is bottom 4 bits - ImageCeeCsCallconvHasthis = 0x20, - // Top bit indicates a 'this' parameter - ImageCeeCsCallconvExplicitthis = 0x40, - // This parameter is explicitly in the signature - ImageCeeCsCallconvGeneric = 0x10, // Generic method sig with explicit number of type arguments (precedes ordinary parameter count) - // 0x80 is reserved for internal use +pub enum CorCallingConvention { + ImageCeeCsCallconvDefault = 0x0, + + ImageCeeCsCallconvVararg = 0x5, + ImageCeeCsCallconvField = 0x6, + ImageCeeCsCallconvLocalSig = 0x7, + ImageCeeCsCallconvProperty = 0x8, + ImageCeeCsCallconvUnmgd = 0x9, + ImageCeeCsCallconvGenericinst = 0xa, + // generic method instantiation + ImageCeeCsCallconvNativevararg = 0xb, + // used ONLY for 64bit vararg PInvoke calls + ImageCeeCsCallconvMax = 0xc, // first invalid calling convention + + // The high bits of the calling convention convey additional info + ImageCeeCsCallconvMask = 0x0f, + // Calling convention is bottom 4 bits + ImageCeeCsCallconvHasthis = 0x20, + // Top bit indicates a 'this' parameter + ImageCeeCsCallconvExplicitthis = 0x40, + // This parameter is explicitly in the signature + ImageCeeCsCallconvGeneric = 0x10, // Generic method sig with explicit number of type arguments (precedes ordinary parameter count) + // 0x80 is reserved for internal use +} + +impl From for CorCallingConvention { + fn from(value: u32) -> Self { + match value { + 0x0 => CorCallingConvention::ImageCeeCsCallconvDefault, + + 0x5 => CorCallingConvention::ImageCeeCsCallconvVararg, + 0x6 => CorCallingConvention::ImageCeeCsCallconvField, + 0x7 => CorCallingConvention::ImageCeeCsCallconvLocalSig, + 0x8 => CorCallingConvention::ImageCeeCsCallconvProperty, + 0x9 => CorCallingConvention::ImageCeeCsCallconvUnmgd, + 0xa => CorCallingConvention::ImageCeeCsCallconvGenericinst, + // generic method instantiation + 0xb => CorCallingConvention::ImageCeeCsCallconvNativevararg, + // used ONLY for 64bit vararg PInvoke calls + 0xc => CorCallingConvention::ImageCeeCsCallconvMax, // first invalid calling convention + + // The high bits of the calling convention convey additional info + 0x0f => CorCallingConvention::ImageCeeCsCallconvMask, + // Calling convention is bottom 4 bits + 0x20 => CorCallingConvention::ImageCeeCsCallconvHasthis, + // Top bit indicates a 'this' parameter + 0x40 => CorCallingConvention::ImageCeeCsCallconvExplicitthis, + // This parameter is explicitly in the signature + 0x10 => CorCallingConvention::ImageCeeCsCallconvGeneric, // Generic method sig with explicit number of type arguments (precedes ordinary parameter count) + // 0x80 is reserved for internal use + _ => std::unreachable!() + } + } } +impl From for u32 { + fn from(value: CorCallingConvention) -> Self { + match value { + CorCallingConvention::ImageCeeCsCallconvDefault => 0x0, + + CorCallingConvention::ImageCeeCsCallconvVararg => 0x5, + CorCallingConvention::ImageCeeCsCallconvField => 0x6, + CorCallingConvention::ImageCeeCsCallconvLocalSig => 0x7, + CorCallingConvention::ImageCeeCsCallconvProperty => 0x8 , + CorCallingConvention::ImageCeeCsCallconvUnmgd => 0x9, + CorCallingConvention::ImageCeeCsCallconvGenericinst => 0xa, + // generic method instantiation + CorCallingConvention::ImageCeeCsCallconvNativevararg => 0xb, + // used ONLY for 64bit vararg PInvoke calls + CorCallingConvention::ImageCeeCsCallconvMax => 0xc, // first invalid calling convention + + // The high bits of the calling convention convey additional info + CorCallingConvention::ImageCeeCsCallconvMask => 0x0f, + // Calling convention is bottom 4 bits + CorCallingConvention::ImageCeeCsCallconvHasthis => 0x20, + // Top bit indicates a 'this' parameter + CorCallingConvention::ImageCeeCsCallconvExplicitthis => 0x40, + // This parameter is explicitly in the signature + CorCallingConvention::ImageCeeCsCallconvGeneric => 0x10, // Generic method sig with explicit number of type arguments (precedes ordinary parameter count) + // 0x80 is reserved for internal use + _ => std::unreachable!() + } + } +} #[derive(Copy, Clone, Debug, PartialEq)] #[repr(C)] -pub enum CorElementType -{ - ElementTypeEnd = 0x00, - ElementTypeVoid = 0x01, - ElementTypeBoolean = 0x02, - ElementTypeChar = 0x03, - ElementTypeI1 = 0x04, - ElementTypeU1 = 0x05, - ElementTypeI2 = 0x06, - ElementTypeU2 = 0x07, - ElementTypeI4 = 0x08, - ElementTypeU4 = 0x09, - ElementTypeI8 = 0x0a, - ElementTypeU8 = 0x0b, - ElementTypeR4 = 0x0c, - ElementTypeR8 = 0x0d, - ElementTypeString = 0x0e, - - // every type above PTR will be simple type - ElementTypePtr = 0x0f, - // PTR - ElementTypeByref = 0x10, // BYREF - - // Please use ElementTypeValuetype. ELEMENT_TYPE_VALUECLASS is deprecated. - ElementTypeValuetype = 0x11, - // VALUETYPE - ElementTypeClass = 0x12, - // CLASS - ElementTypeVar = 0x13, - // a class type variable VAR - ElementTypeArray = 0x14, - // MDARRAY ... ... - ElementTypeGenericinst = 0x15, - // GENERICINST ... - ElementTypeTypedbyref = 0x16, // TYPEDREF (it takes no args) a typed referece to some other type - - ElementTypeI = 0x18, - // native integer size - ElementTypeU = 0x19, - // native unsigned integer size - ElementTypeFnptr = 0x1b, - // FNPTR - ElementTypeObject = 0x1c, - // Shortcut for System.Object - ElementTypeSzarray = 0x1d, - // Shortcut for single dimension zero lower bound array -// SZARRAY - ElementTypeMvar = 0x1e, // a method type variable MVAR - - // This is only for binding - ElementTypeCmodReqd = 0x1f, - // required C modifier : E_T_CMOD_REQD - ElementTypeCmodOpt = 0x20, // optional C modifier : E_T_CMOD_OPT - - // This is for signatures generated internally (which will not be persisted in any way). - ElementTypeInternal = 0x21, // INTERNAL - - // Note that this is the max of base type excluding modifiers - ElementTypeMax = 0x22, // first invalid element type - - - ElementTypeModifier = 0x40, - ElementTypeSentinel = 0x01 | 0x40, - // sentinel for varargs - ElementTypePinned = 0x05 | 0x40, +pub enum CorElementType { + ElementTypeEnd = 0x00, + ElementTypeVoid = 0x01, + ElementTypeBoolean = 0x02, + ElementTypeChar = 0x03, + ElementTypeI1 = 0x04, + ElementTypeU1 = 0x05, + ElementTypeI2 = 0x06, + ElementTypeU2 = 0x07, + ElementTypeI4 = 0x08, + ElementTypeU4 = 0x09, + ElementTypeI8 = 0x0a, + ElementTypeU8 = 0x0b, + ElementTypeR4 = 0x0c, + ElementTypeR8 = 0x0d, + ElementTypeString = 0x0e, + + // every type above PTR will be simple type + ElementTypePtr = 0x0f, + // PTR + ElementTypeByref = 0x10, // BYREF + + // Please use ElementTypeValuetype. ELEMENT_TYPE_VALUECLASS is deprecated. + ElementTypeValuetype = 0x11, + // VALUETYPE + ElementTypeClass = 0x12, + // CLASS + ElementTypeVar = 0x13, + // a class type variable VAR + ElementTypeArray = 0x14, + // MDARRAY ... ... + ElementTypeGenericinst = 0x15, + // GENERICINST ... + ElementTypeTypedbyref = 0x16, // TYPEDREF (it takes no args) a typed referece to some other type + + ElementTypeI = 0x18, + // native integer size + ElementTypeU = 0x19, + // native unsigned integer size + ElementTypeFnptr = 0x1b, + // FNPTR + ElementTypeObject = 0x1c, + // Shortcut for System.Object + ElementTypeSzarray = 0x1d, + // Shortcut for single dimension zero lower bound array + // SZARRAY + ElementTypeMvar = 0x1e, // a method type variable MVAR + + // This is only for binding + ElementTypeCmodReqd = 0x1f, + // required C modifier : E_T_CMOD_REQD + ElementTypeCmodOpt = 0x20, // optional C modifier : E_T_CMOD_OPT + // This is for signatures generated internally (which will not be persisted in any way). + ElementTypeInternal = 0x21, // INTERNAL + + // Note that this is the max of base type excluding modifiers + ElementTypeMax = 0x22, // first invalid element type + + ElementTypeModifier = 0x40, + ElementTypeSentinel = 0x01 | 0x40, + // sentinel for varargs + ElementTypePinned = 0x05 | 0x40, } impl From for CorElementType { - fn from(cet: core_bindings::CorElementType) -> Self { - match cet { - core_bindings::CorElementType::ELEMENT_TYPE_END => CorElementType::ElementTypeEnd, - core_bindings::CorElementType::ELEMENT_TYPE_VOID => CorElementType::ElementTypeVoid, - core_bindings::CorElementType::ELEMENT_TYPE_BOOLEAN => CorElementType::ElementTypeBoolean, - core_bindings::CorElementType::ELEMENT_TYPE_CHAR => CorElementType::ElementTypeChar, - core_bindings::CorElementType::ELEMENT_TYPE_I1 => CorElementType::ElementTypeI1, - core_bindings::CorElementType::ELEMENT_TYPE_U1 => CorElementType::ElementTypeU1, - core_bindings::CorElementType::ELEMENT_TYPE_I2 => CorElementType::ElementTypeI2, - core_bindings::CorElementType::ELEMENT_TYPE_U2 => CorElementType::ElementTypeU2, - core_bindings::CorElementType::ELEMENT_TYPE_I4 => CorElementType::ElementTypeI4, - core_bindings::CorElementType::ELEMENT_TYPE_U4 => CorElementType::ElementTypeU4, - core_bindings::CorElementType::ELEMENT_TYPE_I8 => CorElementType::ElementTypeI8, - core_bindings::CorElementType::ELEMENT_TYPE_U8 => CorElementType::ElementTypeU8, - core_bindings::CorElementType::ELEMENT_TYPE_R4 => CorElementType::ElementTypeR4, - core_bindings::CorElementType::ELEMENT_TYPE_R8 => CorElementType::ElementTypeR8, - core_bindings::CorElementType::ELEMENT_TYPE_STRING => CorElementType::ElementTypeString, - core_bindings::CorElementType::ELEMENT_TYPE_PTR => CorElementType::ElementTypePtr, - core_bindings::CorElementType::ELEMENT_TYPE_BYREF => CorElementType::ElementTypeByref, - core_bindings::CorElementType::ELEMENT_TYPE_VALUETYPE => CorElementType::ElementTypeValuetype, - core_bindings::CorElementType::ELEMENT_TYPE_CLASS => CorElementType::ElementTypeClass, - core_bindings::CorElementType::ELEMENT_TYPE_VAR => CorElementType::ElementTypeVar, - core_bindings::CorElementType::ELEMENT_TYPE_ARRAY => CorElementType::ElementTypeArray, - core_bindings::CorElementType::ELEMENT_TYPE_GENERICINST => CorElementType::ElementTypeGenericinst, - core_bindings::CorElementType::ELEMENT_TYPE_TYPEDBYREF => CorElementType::ElementTypeTypedbyref, - core_bindings::CorElementType::ELEMENT_TYPE_I => CorElementType::ElementTypeI, - core_bindings::CorElementType::ELEMENT_TYPE_U => CorElementType::ElementTypeU, - core_bindings::CorElementType::ELEMENT_TYPE_FNPTR => CorElementType::ElementTypeFnptr, - core_bindings::CorElementType::ELEMENT_TYPE_OBJECT => CorElementType::ElementTypeObject, - core_bindings::CorElementType::ELEMENT_TYPE_SZARRAY => CorElementType::ElementTypeSzarray, - core_bindings::CorElementType::ELEMENT_TYPE_MVAR => CorElementType::ElementTypeMvar, - core_bindings::CorElementType::ELEMENT_TYPE_CMOD_REQD => CorElementType::ElementTypeCmodReqd, - core_bindings::CorElementType::ELEMENT_TYPE_CMOD_OPT => CorElementType::ElementTypeCmodOpt, - core_bindings::CorElementType::ELEMENT_TYPE_INTERNAL => CorElementType::ElementTypeInternal, - core_bindings::CorElementType::ELEMENT_TYPE_MAX => CorElementType::ElementTypeMax, - core_bindings::CorElementType::ELEMENT_TYPE_MODIFIER => CorElementType::ElementTypeModifier, - core_bindings::CorElementType::ELEMENT_TYPE_SENTINEL => CorElementType::ElementTypeSentinel, - core_bindings::CorElementType::ELEMENT_TYPE_PINNED => CorElementType::ElementTypePinned, - } - } + fn from(cet: core_bindings::CorElementType) -> Self { + match cet { + core_bindings::CorElementType::ELEMENT_TYPE_END => CorElementType::ElementTypeEnd, + core_bindings::CorElementType::ELEMENT_TYPE_VOID => CorElementType::ElementTypeVoid, + core_bindings::CorElementType::ELEMENT_TYPE_BOOLEAN => { + CorElementType::ElementTypeBoolean + } + core_bindings::CorElementType::ELEMENT_TYPE_CHAR => CorElementType::ElementTypeChar, + core_bindings::CorElementType::ELEMENT_TYPE_I1 => CorElementType::ElementTypeI1, + core_bindings::CorElementType::ELEMENT_TYPE_U1 => CorElementType::ElementTypeU1, + core_bindings::CorElementType::ELEMENT_TYPE_I2 => CorElementType::ElementTypeI2, + core_bindings::CorElementType::ELEMENT_TYPE_U2 => CorElementType::ElementTypeU2, + core_bindings::CorElementType::ELEMENT_TYPE_I4 => CorElementType::ElementTypeI4, + core_bindings::CorElementType::ELEMENT_TYPE_U4 => CorElementType::ElementTypeU4, + core_bindings::CorElementType::ELEMENT_TYPE_I8 => CorElementType::ElementTypeI8, + core_bindings::CorElementType::ELEMENT_TYPE_U8 => CorElementType::ElementTypeU8, + core_bindings::CorElementType::ELEMENT_TYPE_R4 => CorElementType::ElementTypeR4, + core_bindings::CorElementType::ELEMENT_TYPE_R8 => CorElementType::ElementTypeR8, + core_bindings::CorElementType::ELEMENT_TYPE_STRING => CorElementType::ElementTypeString, + core_bindings::CorElementType::ELEMENT_TYPE_PTR => CorElementType::ElementTypePtr, + core_bindings::CorElementType::ELEMENT_TYPE_BYREF => CorElementType::ElementTypeByref, + core_bindings::CorElementType::ELEMENT_TYPE_VALUETYPE => { + CorElementType::ElementTypeValuetype + } + core_bindings::CorElementType::ELEMENT_TYPE_CLASS => CorElementType::ElementTypeClass, + core_bindings::CorElementType::ELEMENT_TYPE_VAR => CorElementType::ElementTypeVar, + core_bindings::CorElementType::ELEMENT_TYPE_ARRAY => CorElementType::ElementTypeArray, + core_bindings::CorElementType::ELEMENT_TYPE_GENERICINST => { + CorElementType::ElementTypeGenericinst + } + core_bindings::CorElementType::ELEMENT_TYPE_TYPEDBYREF => { + CorElementType::ElementTypeTypedbyref + } + core_bindings::CorElementType::ELEMENT_TYPE_I => CorElementType::ElementTypeI, + core_bindings::CorElementType::ELEMENT_TYPE_U => CorElementType::ElementTypeU, + core_bindings::CorElementType::ELEMENT_TYPE_FNPTR => CorElementType::ElementTypeFnptr, + core_bindings::CorElementType::ELEMENT_TYPE_OBJECT => CorElementType::ElementTypeObject, + core_bindings::CorElementType::ELEMENT_TYPE_SZARRAY => { + CorElementType::ElementTypeSzarray + } + core_bindings::CorElementType::ELEMENT_TYPE_MVAR => CorElementType::ElementTypeMvar, + core_bindings::CorElementType::ELEMENT_TYPE_CMOD_REQD => { + CorElementType::ElementTypeCmodReqd + } + core_bindings::CorElementType::ELEMENT_TYPE_CMOD_OPT => { + CorElementType::ElementTypeCmodOpt + } + core_bindings::CorElementType::ELEMENT_TYPE_INTERNAL => { + CorElementType::ElementTypeInternal + } + core_bindings::CorElementType::ELEMENT_TYPE_MAX => CorElementType::ElementTypeMax, + core_bindings::CorElementType::ELEMENT_TYPE_MODIFIER => { + CorElementType::ElementTypeModifier + } + core_bindings::CorElementType::ELEMENT_TYPE_SENTINEL => { + CorElementType::ElementTypeSentinel + } + core_bindings::CorElementType::ELEMENT_TYPE_PINNED => CorElementType::ElementTypePinned, + } + } } - #[derive(Debug, Clone, Copy, PartialEq)] #[repr(C)] pub enum CorTokenType { - mdtModule = 0x00000000, - mdtTypeRef = 0x01000000, - mdtTypeDef = 0x02000000, - mdtFieldDef = 0x04000000, - mdtMethodDef = 0x06000000, - mdtParamDef = 0x08000000, - mdtInterfaceImpl = 0x09000000, - mdtMemberRef = 0x0a000000, - mdtCustomAttribute = 0x0c000000, - mdtPermission = 0x0e000000, - mdtSignature = 0x11000000, - mdtEvent = 0x14000000, - mdtProperty = 0x17000000, - mdtModuleRef = 0x1a000000, - mdtTypeSpec = 0x1b000000, - mdtAssembly = 0x20000000, - mdtAssemblyRef = 0x23000000, - mdtFile = 0x26000000, - mdtExportedType = 0x27000000, - mdtManifestResource = 0x28000000, - mdtGenericParam = 0x2a000000, - mdtMethodSpec = 0x2b000000, - mdtGenericParamConstraint = 0x2c000000, - mdtString = 0x70000000, - mdtName = 0x71000000, - mdtBaseType = 0x72000000, - mdtError_ = 1868 + mdtModule = 0x00000000, + mdtTypeRef = 0x01000000, + mdtTypeDef = 0x02000000, + mdtFieldDef = 0x04000000, + mdtMethodDef = 0x06000000, + mdtParamDef = 0x08000000, + mdtInterfaceImpl = 0x09000000, + mdtMemberRef = 0x0a000000, + mdtCustomAttribute = 0x0c000000, + mdtPermission = 0x0e000000, + mdtSignature = 0x11000000, + mdtEvent = 0x14000000, + mdtProperty = 0x17000000, + mdtModuleRef = 0x1a000000, + mdtTypeSpec = 0x1b000000, + mdtAssembly = 0x20000000, + mdtAssemblyRef = 0x23000000, + mdtFile = 0x26000000, + mdtExportedType = 0x27000000, + mdtManifestResource = 0x28000000, + mdtGenericParam = 0x2a000000, + mdtMethodSpec = 0x2b000000, + mdtGenericParamConstraint = 0x2c000000, + mdtString = 0x70000000, + mdtName = 0x71000000, + mdtBaseType = 0x72000000 } impl From for CorTokenType { - fn from(value: u32) -> Self { - match value { - 0x00000000 => Self::mdtModule, - 0x01000000 => Self::mdtTypeRef, - 0x02000000 => Self::mdtTypeDef, - 0x04000000 => Self::mdtFieldDef, - 0x06000000 => Self::mdtMethodDef, - 0x08000000 => Self::mdtParamDef, - 0x09000000 => Self::mdtInterfaceImpl, - 0x0a000000 => Self::mdtMemberRef, - 0x0c000000 => Self::mdtCustomAttribute, - 0x0e000000 => Self::mdtPermission, - 0x11000000 => Self::mdtSignature, - 0x14000000 => Self::mdtEvent, - 0x17000000 => Self::mdtProperty, - 0x1a000000 => Self::mdtModuleRef, - 0x1b000000 => Self::mdtTypeSpec, - 0x20000000 => Self::mdtAssembly, - 0x23000000 => Self::mdtAssemblyRef, - 0x26000000 => Self::mdtFile, - 0x27000000 => Self::mdtExportedType, - 0x28000000 => Self::mdtManifestResource, - 0x2a000000 => Self::mdtGenericParam, - 0x2b000000 => Self::mdtMethodSpec, - 0x2c000000 => Self::mdtGenericParamConstraint, - 0x70000000 => Self::mdtString, - 0x71000000 => Self::mdtName, - 0x72000000 => Self::mdtBaseType, - _ => Self::mdtError_ - } - } -} \ No newline at end of file + fn from(value: u32) -> Self { + match value { + 0x00000000 => Self::mdtModule, + 0x01000000 => Self::mdtTypeRef, + 0x02000000 => Self::mdtTypeDef, + 0x04000000 => Self::mdtFieldDef, + 0x06000000 => Self::mdtMethodDef, + 0x08000000 => Self::mdtParamDef, + 0x09000000 => Self::mdtInterfaceImpl, + 0x0a000000 => Self::mdtMemberRef, + 0x0c000000 => Self::mdtCustomAttribute, + 0x0e000000 => Self::mdtPermission, + 0x11000000 => Self::mdtSignature, + 0x14000000 => Self::mdtEvent, + 0x17000000 => Self::mdtProperty, + 0x1a000000 => Self::mdtModuleRef, + 0x1b000000 => Self::mdtTypeSpec, + 0x20000000 => Self::mdtAssembly, + 0x23000000 => Self::mdtAssemblyRef, + 0x26000000 => Self::mdtFile, + 0x27000000 => Self::mdtExportedType, + 0x28000000 => Self::mdtManifestResource, + 0x2a000000 => Self::mdtGenericParam, + 0x2b000000 => Self::mdtMethodSpec, + 0x2c000000 => Self::mdtGenericParamConstraint, + 0x70000000 => Self::mdtString, + 0x71000000 => Self::mdtName, + 0x72000000 => Self::mdtBaseType, + _ => std::unreachable!() + } + } +} diff --git a/core/src/lib.rs b/core/src/lib.rs index d73b194..6c90aae 100755 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -3,9 +3,3 @@ pub mod metadata; pub mod bindings; pub mod prelude; pub mod enums; - -#[no_mangle] -pub extern fn hello(){ - println!("Hello from rust") -} - diff --git a/core/src/metadata/com_helpers.rs b/core/src/metadata/com_helpers.rs index 559b64f..29d33b5 100755 --- a/core/src/metadata/com_helpers.rs +++ b/core/src/metadata/com_helpers.rs @@ -1,8 +1,8 @@ +use crate::bindings::{enums, helpers, rometadataresolution}; use crate::prelude::*; -use crate::bindings::{helpers, imeta_data_import2, enums, rometadataresolution}; +use core_bindings::GUID; use std::borrow::Cow; - const GUID_ATTRIBUTE: &str = "Windows.Foundation.Metadata.GuidAttribute"; pub const SYSTEM_TYPE: &str = "System.Type"; @@ -10,109 +10,157 @@ pub const STATIC_ATTRIBUTE: &str = "Windows.Foundation.Metadata.StaticAttribute" pub const ACTIVATABLE_ATTRIBUTE: &str = "Windows.Foundation.Metadata.ActivatableAttribute"; pub const COMPOSABLE_ATTRIBUTE: &str = "Windows.Foundation.Metadata.ComposableAttribute"; +pub fn get_string_value_from_blob<'a>( + metadata: &IMetaDataImport2, + signature: PCCOR_SIGNATURE, +) -> Cow<'a, str> { + debug_assert!(metadata.is_none()); + debug_assert!(signature.is_null()); -pub fn get_string_value_from_blob<'a>(metadata: *mut IMetaDataImport2, signature: PCCOR_SIGNATURE) -> Cow<'a, str> { - debug_assert!(!metadata.is_null()); - debug_assert!(!signature.is_null()); - - if signature as u8 == u8::MAX { - return "".into(); - } + if signature as u8 == u8::MAX { + return "".into(); + } - let size = helpers::cor_sig_uncompress_data(signature); + let size = helpers::cor_sig_uncompress_data(signature); - let slice = unsafe { std::slice::from_raw_parts(signature as *mut u16, size as usize) }; + let slice = unsafe { std::slice::from_raw_parts(signature as *mut u16, size as usize) }; - windows::HSTRING::from_wide(slice).to_string_lossy().into() + windows::HSTRING::from_wide(slice).to_string_lossy().into() } - -pub fn get_unary_custom_attribute_string_value<'a>(metadata: *mut c_void, token: mdToken, attribute_name: &str) -> Cow<'a, str> { - debug_assert!(!metadata.is_null()); - debug_assert!(token != mdTokenNil); - debug_assert!(!attribute_name.is_null()); - - - let mut data = vec![0_u8; MAX_IDENTIFIER_LENGTH]; - let name = OsString::from(attribute_name.to_owned()).to_wide(); - let data_ptr = &data.as_mut_ptr() as *mut *const c_void; - let result = imeta_data_import2::get_custom_attribute_by_name( - metadata, token, Some(name.as_ptr()), Some(data_ptr), None, - ); - debug_assert!( - result.is_ok() - ); - if result.is_err() { - return "".into(); - } - - get_string_value_from_blob(metadata, data + 2) +pub fn get_unary_custom_attribute_string_value<'a>( + metadata: Option<&IMetaDataImport2>, + token: mdToken, + attribute_name: &str, +) -> Cow<'a, str> { + debug_assert!(metadata.is_none()); + debug_assert!(token != mdTokenNil); + debug_assert!(!attribute_name.is_null()); + + match metadata { + None => Cow::default(), + Some(metadata) => { + let mut data = std::mem::MaybeUninit::uninit(); + let name = OsString::from(attribute_name).to_wide(); + let data_ptr = &mut data.as_mut_ptr() as *mut *const c_void; + + let result = + metadata.get_custom_attribute_by_name(token, Some(&name), Some(data_ptr), None); + debug_assert!(result.is_ok()); + if result.is_err() { + return "".into(); + } + + let mut data = unsafe { data.assume_init() }; + + get_string_value_from_blob(metadata, data + 2) + } + } } - -pub fn resolve_type_ref(metadata: *mut IMetaDataImport2, token: mdTypeRef, external_metadata: *mut *mut c_void, external_token: *mut mdTypeDef) -> bool { - debug_assert!(!metadata.is_null()); - debug_assert!(enums::type_from_token(token) == CorTokenType::mdtTypeRef as u32); - debug_assert!(!external_metadata.is_null()); - debug_assert!(!external_token.is_null()); - - let mut data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; - debug_assert!( - imeta_data_import2::get_type_ref_props( - metadata, token, None, Some(data.as_mut_ptr()), Some(data.len() as u32), None, - ).is_ok() - ); - let mut string = windows::HSTRING::from_wide(data.as_slice()); - rometadataresolution::ro_get_meta_data_file( - &mut string, None, None, Some(external_metadata), Some(external_token), - ).is_ok() +pub fn resolve_type_ref( + metadata: Option<&IMetaDataImport2>, + token: mdTypeRef, + external_metadata: &mut IMetaDataImport2, + external_token: &mut mdTypeDef, +) -> bool { + debug_assert!(metadata.is_none()); + debug_assert!(CorTokenType::from(enums::type_from_token(token)) == CorTokenType::mdtTypeRef); + //debug_assert!(!external_metadata.is_null()); + //debug_assert!(!external_token.is_null()); + + match metadata { + None => false, + Some(metadata) => { + let mut data = [0_u16; MAX_IDENTIFIER_LENGTH]; + let result = metadata.get_type_ref_props( + token, + None, + Some(&data), + Some(data.len() as u32), + None, + ); + debug_assert!(result.is_ok()); + let mut string = windows::HSTRING::from_wide(&data); + let mut external_metadata = external_metadata as *mut _; + rometadataresolution::ro_get_meta_data_file( + &mut string, + None, + None, + Some(&mut external_metadata), + Some(external_token), + ) + .is_ok() + } + } } - -pub fn get_guid_attribute_value(metadata: *mut IMetaDataImport2, token: mdToken) -> GUID { - debug_assert!(!metadata.is_null()); - debug_assert!(token != mdTokenNil); - let mut size = 0; - let mut data = vec![0_u8; MAX_IDENTIFIER_LENGTH]; - let name = OsString::from(GUID_ATTRIBUTE).to_wide(); - let data_ptr = &data.as_mut_ptr() as *mut *const c_void; - imeta_data_import2::get_custom_attribute_by_name( - metadata, token, Some(name.as_ptr()), Some(data_ptr), Some(&mut size), - ); - data.resize(size as _, 0); - - // Skip prolog - let os_data = unsafe { data.as_mut_ptr().offset(2) }; - let mut guid = GUID::default(); - helpers::bytes_to_guid( - os_data, &mut guid, - ); - guid +pub fn get_guid_attribute_value(metadata: Option<&IMetaDataImport2>, token: mdToken) -> GUID { + debug_assert!(metadata.is_none()); + debug_assert!(token != mdTokenNil); + + let mut guid = GUID::default(); + + match metadata { + None => {} + Some(_) => { + let mut size = 0; + let mut data = std::mem::MaybeUninit::uninit(); + let name = OsString::from(GUID_ATTRIBUTE).to_wide(); + let data_ptr = &mut data.as_mut_ptr() as *mut *const c_void; + + metadata.get_custom_attribute_by_name( + token, + Some(name.as_slice()), + Some(data_ptr), + Some(&mut size), + ); + + let mut data = unsafe { data.assume_init() }; + // Skip prolog + let os_data = unsafe { data.as_mut_ptr().offset(2) }; + + helpers::bytes_to_guid(os_data, &mut guid); + } + } + guid } -pub fn get_type_name<'a>(metadata: *mut IMetaDataImport2, token: mdToken) -> Cow<'a, str> { - debug_assert!(!metadata.is_null()); - debug_assert!(token != mdTokenNil); - - let mut name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; - let mut name_length = 0; - match CorTokenType::from(enums::type_from_token(token)) { - CorTokenType::mdtTypeDef => { - debug_assert!(imeta_data_import2::get_type_def_props( - metadata, token, Some(name_data.as_mut_ptr()), Some(name_data.len() as u32), Some(&mut name_length), None, None, - ).is_ok()); - } - CorTokenType::mdtTypeRef => { - debug_assert!( - imeta_data_import2::get_type_ref_props( - metadata, token, None, Some(name_data.as_mut_ptr()), Some(name_data.len() as u32), Some(&mut name_length), - ).is_ok() - ); - } - _ => { - std::unreachable!() - } - } - - OsString::from_wide(name_data[..name_length]).into() -} \ No newline at end of file +pub fn get_type_name<'a>(metadata: Option<&IMetaDataImport2>, token: mdToken) -> Cow<'a, str> { + debug_assert!(metadata.is_none()); + debug_assert!(token != mdTokenNil); + + let mut name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; + let mut name_length = 0; + match CorTokenType::from(enums::type_from_token(token)) { + CorTokenType::mdtTypeDef => { + if let Some(metadata) = metadata { + let result = metadata.get_type_def_props( + token, + Some(&mut name_data), + Some(name_data.len() as u32), + Some(&mut name_length), + None, + None, + ); + debug_assert!(result.is_ok()) + } + } + CorTokenType::mdtTypeRef => { + let result = metadata.get_type_ref_props( + metadata, + token, + None, + Some(name_data.as_mut_ptr()), + Some(name_data.len() as u32), + Some(&mut name_length), + ); + debug_assert!(result.is_ok()); + } + _ => { + core_unreachable(); + } + } + + OsString::from_wide(name_data[..name_length]).into() +} diff --git a/core/src/metadata/declaration_factory.rs b/core/src/metadata/declaration_factory.rs index 7745212..d0da535 100644 --- a/core/src/metadata/declaration_factory.rs +++ b/core/src/metadata/declaration_factory.rs @@ -1,6 +1,6 @@ -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, Mutex, RwLock}; -use crate::bindings::{enums, helpers, imeta_data_import2}; +use crate::bindings::{enums, helpers}; use crate::metadata::com_helpers::resolve_type_ref; use crate::metadata::declarations::base_class_declaration::BaseClassDeclarationImpl; @@ -14,20 +14,29 @@ use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; pub struct DeclarationFactory {} impl DeclarationFactory { - pub fn make_delegate_declaration<'b>(metadata: Arc>, token: mdToken) -> Box { + pub fn make_delegate_declaration(metadata: Option>>, token: mdToken) -> Option>> { match CorTokenType::from(enums::type_from_token(token)) { CorTokenType::mdtTypeDef => Box::new(DelegateDeclaration::new(metadata, token)), CorTokenType::mdtTypeRef => { - let metadata = get_mutex_value_mut(&metadata); - let mut external_metadata = std::mem::MaybeUninit::uninit(); - let external_metadata_ptr = &mut external_metadata.as_ptr(); - let mut external_delegate_token = mdTokenNil; - let is_resolved = resolve_type_ref(metadata, token, external_metadata_ptr as *mut *mut c_void, &mut external_delegate_token); - debug_assert!(is_resolved); - Box::new(DelegateDeclaration::new(Arc::new(Mutex::new( - unsafe { external_metadata.assume_init() } - )), external_delegate_token)) + match get_lock_value(&metadata) { + None => {} + Some(metadata) => { + let mut external_metadata = std::mem::MaybeUninit::uninit(); + let external_metadata_ptr = &mut external_metadata.as_mut_ptr(); + let mut external_delegate_token = mdTokenNil; + let is_resolved = resolve_type_ref(Some(metadata), token, external_metadata_ptr, &mut external_delegate_token); + debug_assert!(is_resolved); + let external_metadata = unsafe { external_metadata.assume_init() }; + Some( + Arc::new( + RwLock::new( + external_metadata + ) + ) + ) + } + } } CorTokenType::mdtTypeSpec => { let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; @@ -76,11 +85,13 @@ impl DeclarationFactory { } } } - pub fn make_interface_declaration(metadata: Arc>, token: mdToken) -> Arc> { + pub fn make_interface_declaration(metadata: Option>>, token: mdToken) -> Option>> { match CorTokenType::from(enums::type_from_token(token)) { CorTokenType::mdtTypeDef => { - Arc::new( - Mutex::new(InterfaceDeclaration::new(metadata, token)) + Some( + Arc::new( + RwLock::new(InterfaceDeclaration::new(metadata, token)) + ) ) } CorTokenType::mdtTypeRef => { diff --git a/core/src/metadata/declarations/base_class_declaration.rs b/core/src/metadata/declarations/base_class_declaration.rs index 55dc031..9cd40f8 100644 --- a/core/src/metadata/declarations/base_class_declaration.rs +++ b/core/src/metadata/declarations/base_class_declaration.rs @@ -1,266 +1,352 @@ -use std::any::Any; use std::borrow::Cow; +use std::sync::{Arc, RwLock}; -use std::sync::{Arc, Mutex}; - +use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; use crate::{ - bindings::imeta_data_import2, - metadata::declaration_factory::DeclarationFactory, - metadata::declarations::declaration::{Declaration, DeclarationKind}, - metadata::declarations::event_declaration::EventDeclaration, - metadata::declarations::method_declaration::MethodDeclaration, - metadata::declarations::property_declaration::PropertyDeclaration, - metadata::declarations::type_declaration::TypeDeclaration, - prelude::*, + metadata::declaration_factory::DeclarationFactory, + metadata::declarations::declaration::{Declaration, DeclarationKind}, + metadata::declarations::event_declaration::EventDeclaration, + metadata::declarations::method_declaration::MethodDeclaration, + metadata::declarations::property_declaration::PropertyDeclaration, + metadata::declarations::type_declaration::TypeDeclaration, + prelude::*, }; -use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; - #[derive(Clone)] pub struct BaseClassDeclaration { - base: TypeDeclaration, - implemented_interfaces: Vec>>, - methods: Vec, - properties: Vec, - events: Vec, + base: TypeDeclaration, + implemented_interfaces: Vec>>, + methods: Vec, + properties: Vec, + events: Vec, } impl BaseClassDeclaration { - fn make_implemented_interfaces_declarations(metadata: Arc>, token: mdTypeDef) -> Vec>> { - let mut enumerator = std::ptr::null_mut(); - let enumerator_ptr = &mut enumerator; - let mut count = 0; - let mut tokens = [0; 1024]; - - let metadata_inner = get_mutex_value_mut(&metadata); - debug_assert!( - imeta_data_import2::enum_interface_impls( - metadata_inner, enumerator_ptr, Some(token), Some(tokens.as_mut_ptr()), Some(tokens.len() as u32), Some(&mut count), - ).is_ok() - ); - - debug_assert!(count < (tokens.len() - 1) as u32); - imeta_data_import2::close_enum(metadata_inner, enumerator); - - let mut result = Vec::new(); - - for token in tokens.into_iter() { - let mut interface_token = mdTokenNil; - debug_assert!( - imeta_data_import2::get_interface_impl_props( - metadata_inner, *token, None, Some(&mut interface_token), - ).is_ok() - ); - result.push( - DeclarationFactory::make_interface_declaration( - metadata_inner, interface_token, - ) - ); - } - - result - } - - fn make_method_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec> { - let mut enumerator = std::ptr::null_mut(); - let enumerator_ptr = &mut enumerator; - let mut count = 0; - let mut tokens = [0; 1024]; - debug_assert!( - imeta_data_import2::enum_methods( - metadata, enumerator_ptr, token, tokens.as_mut_ptr(), tokens.len() as u32, &mut count, - ).is_ok() - ); - - debug_assert!(count < (tokens.len() - 1) as u32); - imeta_data_import2::close_enum(metadata, enumerator); - - let mut result = Vec::new(); - for token in tokens.iter() { - let method = MethodDeclaration::new(metadata, *token); - if !method.is_exported() { - continue; - } - result.push(method); - } - - return result; - } - - fn make_property_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec> { - let mut enumerator = std::ptr::null_mut(); - let enumerator_ptr = &mut enumerator; - let mut count = 0; - let mut tokens = [0; 1024]; - - debug_assert!( - imeta_data_import2::enum_properties( - metadata, enumerator_ptr, token, tokens.as_mut_ptr(), tokens.len() as u32, &mut count, - ).is_ok() - ); - debug_assert!(count < (tokens.len() - 1) as u32); - imeta_data_import2::close_enum(metadata, enumerator); - - let mut result = Vec::new(); - for token in tokens.iter() { - let property = PropertyDeclaration::new(metadata, *token); - if !property.is_exported() { - continue; - } - result.push(property); - } - result - } - - fn make_event_declarations<'b>(metadata: *mut c_void, token: mdTypeDef) -> Vec> { - let mut enumerator = std::ptr::null_mut(); - let enumerator_ptr = &mut enumerator; - let mut count = 0; - let mut tokens = [0; 1024]; - - debug_assert!( - imeta_data_import2::enum_events( - metadata, enumerator_ptr, token, tokens.as_mut_ptr(), tokens.len() as u32, &mut count, - ).is_ok() - ); - debug_assert!(count < (tokens.len() - 1) as u32); - imeta_data_import2::close_enum(metadata, enumerator); - - let mut result = Vec::new(); - for token in tokens.iter() { - let event = EventDeclaration::new(metadata, *token); - if !event.is_exported() { - continue; - } - result.push(event); - } - - result - } - - pub fn new(kind: DeclarationKind, metadata: *mut IMetaDataImport2, token: mdTypeDef) -> Self { - Self { - base: TypeDeclaration::new(kind, metadata, token), - implemented_interfaces: BaseClassDeclaration::make_implemented_interfaces_declarations(metadata, token), - methods: BaseClassDeclaration::make_method_declarations(metadata, token), - properties: BaseClassDeclaration::make_property_declarations(metadata, token), - events: BaseClassDeclaration::make_event_declarations(metadata, token), - } - } + pub fn metadata(&self) -> Option<&IMetaDataImport2> { + self.base.metadata() + } + + pub fn make_implemented_interfaces_declarations( + metadata: Option>>, + token: mdTypeDef, + ) -> Vec { + let mut result = Vec::new(); + match Option::as_ref(&metadata) { + None => {} + Some(metadata) => { + let meta = Arc::clone(metadata); + match metadata.try_read() { + Ok(metadata) => { + let mut enumerator = std::ptr::null_mut(); + let enumerator_ptr = &mut enumerator; + let mut count = 0; + let mut tokens = [0; 1024]; + + let result_inner = metadata.enum_interface_impls( + enumerator_ptr, + Some(token), + Some(&mut tokens), + Some(tokens.len() as u32), + Some(&mut count), + ); + debug_assert!(result_inner.is_ok()); + + debug_assert!(count < (tokens.len() - 1) as u32); + metadata.close_enum(enumerator); + + for token in tokens.into_iter() { + let mut interface_token = mdTokenNil; + let result_inner = metadata.get_interface_impl_props( + *token, + None, + Some(&mut interface_token), + ); + debug_assert!(result_inner.is_ok()); + result.push(DeclarationFactory::make_interface_declaration( + Some(Arc::clone(&meta)), + interface_token, + )); + } + } + Err(_) => {} + } + } + } + result + } + + pub fn make_method_declarations( + metadata: Option>>, + token: mdTypeDef, + ) -> Vec { + let mut result = Vec::new(); + match Option::as_ref(&metadata) { + None => {} + Some(metadata) => { + let meta = Arc::clone(&metadata); + match metadata.try_read() { + Ok(metadata) => { + let mut enumerator = std::ptr::null_mut(); + let enumerator_ptr = &mut enumerator; + let mut count = 0; + let mut tokens = [0; 1024]; + let result_inner = metadata.enum_methods( + enumerator_ptr, + token, + &mut tokens, + tokens.len() as u32, + &mut count, + ); + debug_assert!(result_inner.is_ok()); + + debug_assert!(count < (tokens.len() - 1) as u32); + metadata.close_enum(enumerator); + + for token in tokens.iter() { + let method = MethodDeclaration::new(Some(Arc::clone(&meta)), *token); + if !method.is_exported() { + continue; + } + result.push(method); + } + } + Err(_) => {} + } + } + } + + return result; + } + + pub fn make_property_declarations<'b>( + metadata: Option>>, + token: mdTypeDef, + ) -> Vec { + let mut result = Vec::new(); + match Option::as_ref(&metadata) { + None => {} + Some(metadata) => { + let meta = Arc::clone(&metadata); + match metadata.try_read() { + Ok(metadata) => { + let mut enumerator = std::ptr::null_mut(); + let enumerator_ptr = &mut enumerator; + let mut count = 0; + let mut tokens = [0; 1024]; + let result_inner = metadata.enum_properties( + enumerator_ptr, + token, + &mut tokens, + tokens.len() as u32, + &mut count, + ); + debug_assert!(result_inner.is_ok()); + debug_assert!(count < (tokens.len() - 1) as u32); + metadata.close_enum(enumerator); + + for token in tokens.iter() { + let property = + PropertyDeclaration::new(Some(Arc::clone(&meta)), *token); + if !property.is_exported() { + continue; + } + result.push(property); + } + } + Err(_) => {} + } + } + } + result + } + + pub fn make_event_declarations( + metadata: Option>>, + token: mdTypeDef, + ) -> Vec { + let mut result = Vec::new(); + if let Some(metadata) = Option::as_ref(&metadata) { + let meta = Arc::clone(metadata); + match metadata.try_read() { + Ok(metadata) => { + let mut enumerator = std::ptr::null_mut(); + let enumerator_ptr = &mut enumerator; + let mut count = 0; + let mut tokens = [0; 1024]; + + let result_inner = metadata.enum_events( + enumerator_ptr, + token, + &mut tokens, + tokens.len() as u32, + &mut count, + ); + debug_assert!(result_inner.is_ok()); + debug_assert!(count < (tokens.len() - 1) as u32); + metadata.close_enum(enumerator); + + for token in tokens.iter() { + let event = EventDeclaration::new(Some(Arc::clone(&meta)), *token); + if !event.is_exported() { + continue; + } + result.push(event); + } + } + Err(_) => {} + } + } + + result + } + + pub fn new( + kind: DeclarationKind, + metadata: Option>>, + token: mdTypeDef, + ) -> Self { + Self { + base: TypeDeclaration::new( + kind, + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + implemented_interfaces: BaseClassDeclaration::make_implemented_interfaces_declarations( + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + methods: BaseClassDeclaration::make_method_declarations( + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + properties: BaseClassDeclaration::make_property_declarations( + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + events: BaseClassDeclaration::make_event_declarations( + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + } + } } pub trait BaseClassDeclarationImpl { - - fn base(&self) -> &TypeDeclaration; - - fn implemented_interfaces<'a>(&self) -> &Vec>; - - fn methods<'a>(&self) -> &Vec>; - - fn properties<'a>(&self) -> &Vec>; - - fn events<'a>(&self) -> &Vec>; - - fn find_members_with_name(&self, name: &str) -> Vec { - debug_assert!(!name.is_empty()); - - let mut result: Vec> = Vec::new(); - - // let mut methods = self.find_methods_with_name(name).into_iter().map(|item| Box::new(item)).collect(); - // result.append(&mut methods); - - let mut methods = self.find_methods_with_name(name); - for method in methods.into_iter() { - result.push( - Box::new(method) - ); - } - - // let mut properties = self.properties().into_iter().filter(|prop| prop.full_name() == name).collect(); - // result.append(&mut properties); - - let mut properties = self.properties().clone(); - - for property in properties.into_iter() { - if property.full_name() == name { - result.push( - Box::new(property) - ); - } - } - - // let mut events = self.events().into_iter().filter(|event| event.full_name() == name).collect(); - // result.append(&mut events); - - let mut events = self.events().clone(); - - for event in events { - if event.full_name() == name { - result.push( - Box::new(event) - ) - } - } - - return result; - } - - fn find_methods_with_name<'b>(&self, name: &str) -> Vec> { - debug_assert!(!name.is_empty()); - - let mut enumerator = std::mem::MaybeUninit::uninit(); - let enumerator_ptr = &mut enumerator.as_mut_ptr(); - let mut method_tokens: Vec = vec![0; 1024]; - let mut methods_count = 0; - let name = windows::HSTRING::from(name); - let name = name.as_wide(); - let base = self.base(); - debug_assert!( - imeta_data_import2::enum_methods_with_name( - base.metadata, enumerator_ptr, base.token, name.as_ptr(), - method_tokens.as_mut_ptr(), method_tokens.len() as u32, &mut methods_count, - ).is_ok() - ); - imeta_data_import2::close_enum(base.metadata, enumerator.as_mut_ptr()); - - method_tokens.into_iter().map(|method_token| MethodDeclaration::new(base.metadata, method_token)).collect() - } + fn base(&self) -> &TypeDeclaration; + + fn implemented_interfaces<'a>(&self) -> &[InterfaceDeclaration]; + + fn methods<'a>(&self) -> &[MethodDeclaration]; + + fn properties<'a>(&self) -> &[PropertyDeclaration]; + + fn events<'a>(&self) -> &[EventDeclaration]; + + fn find_members_with_name(&self, name: &str) -> Vec { + debug_assert!(!name.is_empty()); + + let mut result: Vec> = Vec::new(); + + // let mut methods = self.find_methods_with_name(name).into_iter().map(|item| Box::new(item)).collect(); + // result.append(&mut methods); + + let mut methods = self.find_methods_with_name(name); + for method in methods.into_iter() { + result.push(Box::new(method)); + } + + // let mut properties = self.properties().into_iter().filter(|prop| prop.full_name() == name).collect(); + // result.append(&mut properties); + + let mut properties = self.properties().clone(); + + for property in properties.into_iter() { + if property.full_name() == name { + result.push(Box::new(property)); + } + } + + // let mut events = self.events().into_iter().filter(|event| event.full_name() == name).collect(); + // result.append(&mut events); + + let mut events = self.events().clone(); + + for event in events { + if event.full_name() == name { + result.push(Box::new(event)) + } + } + + return result; + } + + fn find_methods_with_name(&self, name: &str) -> Vec { + debug_assert!(!name.is_empty()); + let mut method_tokens = [0; 1024]; + let mut meta = None; + if let Some(metadata) = self.base().metadata_shared() { + meta = Some(Arc::clone(&metadata)); + let mut enumerator = std::ptr::null_mut(); + let enumerator_ptr = &mut enumerator; + + let mut methods_count = 0; + let name = windows::HSTRING::from(name); + let name = name.as_wide(); + let base = self.base(); + let result = metadata.enum_methods_with_name( + enumerator_ptr, + base.token(), + name.as_ptr(), + &mut method_tokens, + method_tokens.len() as u32, + &mut methods_count, + ); + debug_assert!(result.is_ok()); + metadata.close_enum(enumerator); + } + + method_tokens + .iter() + .map(|method_token| { + MethodDeclaration::new(Option::as_ref(&meta).map(|v| Arc::clone(v)), *method_token) + }) + .collect() + } } -impl<'a> BaseClassDeclarationImpl for BaseClassDeclaration<'a> { - fn base(&self) -> &TypeDeclaration<'a> { - &self.base - } +impl BaseClassDeclarationImpl for BaseClassDeclaration { + fn base(&self) -> &TypeDeclaration { + &self.base + } - fn implemented_interfaces(&self) -> &Vec>> { - &self.implemented_interfaces - } + fn implemented_interfaces(&self) -> &[Arc>] { + &self.implemented_interfaces + } - fn methods(&self) -> &Vec> { - &self.methods - } + fn methods(&self) -> &[MethodDeclaration] { + &self.methods + } - fn properties(&self) -> &Vec> { - &self.properties - } + fn properties(&self) -> &[PropertyDeclaration] { + &self.properties + } - fn events(&self) -> &Vec> { - &self.events - } + fn events(&self) -> &[EventDeclaration] { + &self.events + } } -impl<'a> Declaration for BaseClassDeclaration<'a> { - fn name<'b>(&self) -> Cow<'b, str> { - self.full_name() - } +impl Declaration for BaseClassDeclaration { + fn name<'b>(&self) -> Cow<'b, str> { + self.full_name() + } - fn full_name<'b>(&self) -> Cow<'b, str> { - self.base().full_name() - } + fn full_name<'b>(&self) -> Cow<'b, str> { + self.base().full_name() + } - fn kind(&self) -> DeclarationKind { - self.base().kind - } + fn kind(&self) -> DeclarationKind { + self.base().kind() + } } - diff --git a/core/src/metadata/declarations/class_declaration.rs b/core/src/metadata/declarations/class_declaration.rs index f1c3d1e..ac3d161 100644 --- a/core/src/metadata/declarations/class_declaration.rs +++ b/core/src/metadata/declarations/class_declaration.rs @@ -1,139 +1,190 @@ use std::borrow::Cow; -use std::str::FromStr; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, RwLock, TryLockError}; -use crate::{ - metadata::declarations::method_declaration::MethodDeclaration -}; -use crate::bindings::{helpers, imeta_data_import2}; -use crate::bindings::helpers::get_type_name; +use crate::bindings::helpers; use crate::metadata::declaration_factory::DeclarationFactory; -use crate::metadata::declarations::base_class_declaration::{BaseClassDeclaration, BaseClassDeclarationImpl}; +use crate::metadata::declarations::base_class_declaration::{ + BaseClassDeclaration, BaseClassDeclarationImpl, +}; use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; -use crate::prelude::*; use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; +use crate::metadata::declarations::method_declaration::MethodDeclaration; +use crate::prelude::*; -const DEFAULT_ATTRIBUTE:&'static str = "Windows.Foundation.Metadata.DefaultAttribute"; +const DEFAULT_ATTRIBUTE: &str = "Windows.Foundation.Metadata.DefaultAttribute"; #[derive(Clone)] -pub struct ClassDeclaration<'a> { - initializers: Vec>, +pub struct ClassDeclaration { + initializers: Vec, default_interface: Option>, - base: BaseClassDeclaration<'a> + base: BaseClassDeclaration, } -impl<'a> ClassDeclaration<'a> { - - fn make_initializer_declarations<'b>(metadata: *mut IMetaDataImport2, token: mdTypeDef) -> Vec>{ - let mut enumerator = std::mem::MaybeUninit::uninit(); - let enumerator_ptr = &mut enumerator.as_mut_ptr(); - let mut count = 0; - let mut tokens = [0;1024]; - - let name = windows::HSTRING::from(COR_CTOR_METHOD_NAME); - let name = name.as_wide(); - debug_assert!( - imeta_data_import2::enum_methods_with_name( - metadata, enumerator_ptr, token, name.as_ptr(), tokens.as_mut_ptr(), - tokens.len() as u32, &mut count - ).is_ok() - ); - - debug_assert!(count < (tokens.len() - 1) as u32); - - imeta_data_import2::close_enum(metadata, enumerator.as_mut_ptr()); - +impl ClassDeclaration { + pub fn make_initializer_declarations( + metadata: Option>>, + token: mdTypeDef, + ) -> Vec { let mut result = Vec::new(); - for i in 0..count as usize { - let method_token = tokens[i]; - - // TODO: Make a InstanceInitializerDeclaration and check this in it's isExported method - let mut flags = 0; - debug_assert!( - imeta_data_import2::get_method_props( - metadata, method_token, None, None, - None, None, Some(&mut flags), None, None, - None, None - ).is_ok() - ); - - if helpers::is_md_public(flags) { - continue; + if let Some(metadata) = Option::as_ref(&metadata) { + let meta = Arc::clone(metadata); + match metadata.try_read() { + Ok(metadata) => { + let mut enumerator = std::ptr::null_mut(); + let enumerator_ptr = &mut enumerator; + let mut count = 0; + let mut tokens = [0; 1024]; + + let name = windows::HSTRING::from(COR_CTOR_METHOD_NAME); + let name = name.as_wide(); + + let result = metadata.enum_methods_with_name( + enumerator_ptr, + token, + name.as_ptr(), + &mut tokens, + tokens.len() as u32, + &mut count, + ); + debug_assert!(result.is_ok()); + + debug_assert!(count < (tokens.len() - 1) as u32); + + metadata.close_enum(enumerator); + + for i in 0..count as usize { + let method_token = tokens[i]; + + // TODO: Make a InstanceInitializerDeclaration and check this in it's isExported method + let mut flags = 0; + let result_inner = metadata.get_method_props( + method_token, + None, + None, + None, + None, + Some(&mut flags), + None, + None, + None, + None, + ); + debug_assert!(result_inner.is_ok()); + + if helpers::is_md_public(flags) { + continue; + } + + result.push(MethodDeclaration::new( + Some(Arc::clone(&meta)), + method_token, + )); + } + } + Err(_) => {} } - - result.push( - MethodDeclaration::new(metadata, method_token) - ); } - return result; + result } - fn make_default_interface(metadata: *mut IMetaDataImport2, token: mdTypeDef) -> Arc> { - let mut interface_impl_tokens = [0;1024]; - let mut interface_impl_count = 0; - let mut interface_enumerator = std::mem::MaybeUninit::uninit(); - let interface_enumerator_ptr = &mut interface_enumerator.as_mut_ptr(); - debug_assert!( - imeta_data_import2::enum_interface_impls( - metadata, interface_enumerator_ptr, Some(token), - Some(interface_impl_tokens.as_mut_ptr()), Some(interface_impl_tokens.len() as u32), - Some(&mut interface_impl_count) - ).is_ok() - ); - - debug_assert!(interface_impl_count < interface_impl_tokens.len() as u32); - imeta_data_import2::close_enum(metadata, interface_enumerator); - let attr = windows::HSTRING::from(DEFAULT_ATTRIBUTE); - let attr = attr.as_wide(); - for i in 0..interface_impl_count as usize { - let interface_impl_token = interface_impl_tokens[i]; - let get_custom_attribute_result = imeta_data_import2::get_custom_attribute_by_name( - metadata, interface_impl_token, Some(attr.as_ptr()), None, None - ); - debug_assert!(get_custom_attribute_result.is_ok()); - if get_custom_attribute_result.is_ok() { - let mut interface_token = mdTokenNil; - debug_assert!( - imeta_data_import2::get_interface_impl_props( - metadata, interface_impl_token, None, Some(&mut interface_token) - ).is_ok() - ); - return DeclarationFactory::make_interface_declaration(metadata, interface_token) + pub fn make_default_interface( + metadata: Option>>, + token: mdTypeDef, + ) -> Option>> { + match Option::as_ref(&metadata) { + None => {} + Some(metadata) => { + let meta = Arc::clone(metadata); + + match metadata.try_read() { + Ok(metadata) => { + let mut interface_impl_tokens = [0; 1024]; + let mut interface_impl_count = 0; + let mut interface_enumerator = std::ptr::null_mut(); + let interface_enumerator_ptr = &mut interface_enumerator; + let result = metadata.enum_interface_impls( + interface_enumerator_ptr, + Some(token), + Some(&mut interface_impl_tokens), + Some(interface_impl_tokens.len() as u32), + Some(&mut interface_impl_count), + ); + debug_assert!(result.is_ok()); + + debug_assert!(interface_impl_count < interface_impl_tokens.len() as u32); + metadata.close_enum(interface_enumerator); + let attr = windows::HSTRING::from(DEFAULT_ATTRIBUTE); + let attr = attr.as_wide(); + for i in 0..interface_impl_count as usize { + let interface_impl_token = interface_impl_tokens[i]; + let get_custom_attribute_result = metadata + .get_custom_attribute_by_name( + interface_impl_token, + Some(attr), + None, + None, + ); + debug_assert!(get_custom_attribute_result.is_ok()); + if get_custom_attribute_result.is_ok() { + let mut interface_token = mdTokenNil; + let result = metadata.get_interface_impl_props( + interface_impl_token, + None, + Some(&mut interface_token), + ); + debug_assert!(result.is_ok()); + return DeclarationFactory::make_interface_declaration( + Some(Arc::clone(&meta)), + interface_token, + ); + } + } + } + Err(_) => {} + } } } - std::unreachable!() + core_unreachable(); + None } - pub fn new(metadata: *mut c_void, token: mdTypeDef)-> Self { + pub fn new(metadata: Option>>, token: mdTypeDef) -> Self { Self { - initializers: ClassDeclaration::make_initializer_declarations(metadata, token), - default_interface: ClassDeclaration::make_default_interface(metadata, token), - base: BaseClassDeclaration::new( - DeclarationKind::Class, metadata, token - ) + initializers: ClassDeclaration::make_initializer_declarations( + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + default_interface: ClassDeclaration::make_default_interface( + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + base: BaseClassDeclaration::new(DeclarationKind::Class, metadata, token), } } pub fn base_full_name<'b>(&self) -> Cow<'b, str> { - let mut parent_token = mdTokenNil; - let base = self.base.base(); - debug_assert!( - imeta_data_import2::get_type_def_props( - base.metadata, - base.token, - None, None,None,None, - Some(&mut parent_token) - ).is_ok() - ); let mut name = [0_u16; MAX_IDENTIFIER_LENGTH]; - let count = get_type_name(base.metadata, parent_token, name.as_mut_ptr(), name.len() as u32); + let mut count = 0; + let mut parent_token = mdTokenNil; + if let Some(metadata) = self.base.metadata() { + let result = metadata.get_type_def_props( + self.base.base().token(), + None, + None, + None, + None, + Some(&mut parent_token), + ); + debug_assert!(result.is_ok()); + count = helpers::get_type_name(metadata, parent_token, &mut name); + } OsString::from_wide(&name[..count as usize]).to_string_lossy() } - pub fn default_interface(&self) -> &InterfaceDeclaration{ + pub fn default_interface(&self) -> &InterfaceDeclaration { &self.default_interface } @@ -143,22 +194,26 @@ impl<'a> ClassDeclaration<'a> { pub fn is_sealed(&self) -> bool { let mut flags = 0; - let base = self.base.base(); - debug_assert!( - imeta_data_import2::get_type_def_props( - base.metadata, base.token, None, None, None, Some(&mut flags), None - ).is_ok() - ); + if let Some(metadata) = self.base.base().metadata() { + let result = metadata.get_type_def_props( + self.base.base().token(), + None, + None, + None, + Some(&mut flags), + None, + ); + debug_assert!(result.is_ok()); + } helpers::is_td_sealed(flags) } - pub fn initializers(&self) -> &[MethodDeclaration<'a>] { - self.initializers.as_slice() + pub fn initializers(&self) -> &[MethodDeclaration] { + self.initializers.as_slice() } } - -impl <'a> Declaration for ClassDeclaration <'a> { +impl Declaration for ClassDeclaration { fn name<'b>(&self) -> Cow<'b, str> { self.base.name() } @@ -170,4 +225,4 @@ impl <'a> Declaration for ClassDeclaration <'a> { fn kind(&self) -> DeclarationKind { self.base.kind() } -} \ No newline at end of file +} diff --git a/core/src/metadata/declarations/declaration.rs b/core/src/metadata/declarations/declaration.rs index f7779e5..f37ed69 100644 --- a/core/src/metadata/declarations/declaration.rs +++ b/core/src/metadata/declarations/declaration.rs @@ -1,42 +1,41 @@ -use std::borrow::Cow; use std::any::Any; +use std::borrow::Cow; #[derive(Copy, Clone, Debug, PartialEq)] pub enum DeclarationKind { - Namespace, - Class, - Interface, - GenericInterface, - GenericInterfaceInstance, - Enum, - EnumMember, - Struct, - StructField, - Delegate, - GenericDelegate, - GenericDelegateInstance, - Event, - Property, - Method, - Parameter, + Namespace, + Class, + Interface, + GenericInterface, + GenericInterfaceInstance, + Enum, + EnumMember, + Struct, + StructField, + Delegate, + GenericDelegate, + GenericDelegateInstance, + Event, + Property, + Method, + Parameter, } pub trait Declaration { - fn is_exported(&self) -> bool { - return true; - } - - /// Specifies the simple name (e.g., "String" rather than "System.String") of a given type. - fn name<'a>(&self) -> Cow<'a, str>; + fn is_exported(&self) -> bool { + return true; + } - /// Specifies the fully-qualified name of a given type. - /// For generic types, this includes the spelling of generic parameter names. - fn full_name<'a>(&self) -> Cow<'a, str>; + /// Specifies the simple name (e.g., "String" rather than "System.String") of a given type. + fn name<'a>(&self) -> Cow<'a, str>; - fn kind(&self) -> DeclarationKind; + /// Specifies the fully-qualified name of a given type. + /// For generic types, this includes the spelling of generic parameter names. + fn full_name<'a>(&self) -> Cow<'a, str>; - fn as_any(value: &T) -> &dyn Any { - value as &dyn Any - } + fn kind(&self) -> DeclarationKind; + fn as_any(&self) -> &dyn Any { + self as &dyn Any + } } diff --git a/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs b/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs index 51acfaf..98afeee 100644 --- a/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs +++ b/core/src/metadata/declarations/delegate_declaration/generic_delegate_declaration.rs @@ -1,66 +1,74 @@ use std::borrow::Cow; -use core_bindings::{mdToken, IMetaDataImport2}; - -use crate::bindings::imeta_data_import2; use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; -use crate::metadata::declarations::delegate_declaration::{DelegateDeclaration, DelegateDeclarationImpl}; +use crate::metadata::declarations::delegate_declaration::{ + DelegateDeclaration, DelegateDeclarationImpl, +}; use crate::metadata::declarations::method_declaration::MethodDeclaration; use crate::metadata::declarations::type_declaration::TypeDeclaration; -use std::sync::{Arc, Mutex}; +use crate::prelude::*; +use core_bindings::mdToken; +use std::sync::{Arc, RwLock}; #[derive(Clone, Debug)] pub struct GenericDelegateDeclaration { - base: DelegateDeclaration, + base: DelegateDeclaration, } impl GenericDelegateDeclaration { - pub fn new(metadata: Arc>, token: mdToken) -> Self { - Self { - base: DelegateDeclaration::new_overload( - DeclarationKind::GenericDelegate, metadata, token, - ) - } - } - - pub fn number_of_generic_parameters(&self) -> usize { - let mut count = 0; + pub fn new(metadata: Option>>, token: mdToken) -> Self { + Self { + base: DelegateDeclaration::new_overload( + DeclarationKind::GenericDelegate, + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + } + } - let mut enumerator = std::ptr::null_mut(); - let enumerator_ptr = &mut enumerator; + pub fn number_of_generic_parameters(&self) -> usize { + let mut count = 0; - debug_assert!( - imeta_data_import2::enum_generic_params(self.base.base.metadata_mut(), enumerator_ptr, self.base.base.token, None, None, None).is_ok() - ); - debug_assert!( - imeta_data_import2::count_enum(self.base.base.metadata_mut(), enumerator, &mut count).is_ok() - ); - imeta_data_import2::close_enum(self.base.base.metadata_mut(), enumerator); + if let Some(metadata) = self.base.base.metadata() { + let mut enumerator = std::ptr::null_mut(); + let enumerator_ptr = &mut enumerator; + let result = metadata.enum_generic_params( + enumerator_ptr, + self.base.base.token(), + None, + None, + None, + ); + debug_assert!(result.is_ok()); - return count as usize; - } + let result = metadata.count_enum(enumerator, &mut count); + debug_assert!(result.is_ok()); + metadata.close_enum(enumerator); + } + return count as usize; + } } impl Declaration for GenericDelegateDeclaration { - fn name<'b>(&self) -> Cow<'b, str> { - self.base.name() - } + fn name<'b>(&self) -> Cow<'b, str> { + self.base.name() + } - fn full_name<'b>(&self) -> Cow<'b, str> { - self.base.full_name() - } + fn full_name<'b>(&self) -> Cow<'b, str> { + self.base.full_name() + } - fn kind(&self) -> DeclarationKind { - self.base.kind() - } + fn kind(&self) -> DeclarationKind { + self.base.kind() + } } impl DelegateDeclarationImpl for GenericDelegateDeclaration { - fn base<'b>(&self) -> &'b TypeDeclaration { - &self.base.base - } + fn base<'b>(&self) -> &'b TypeDeclaration { + &self.base.base + } - fn invoke_method<'b>(&self) -> &'b MethodDeclaration { - &self.base.invoke_method - } -} \ No newline at end of file + fn invoke_method<'b>(&self) -> &'b MethodDeclaration { + &self.base.invoke_method + } +} diff --git a/core/src/metadata/declarations/delegate_declaration/generic_delegate_instance_declaration.rs b/core/src/metadata/declarations/delegate_declaration/generic_delegate_instance_declaration.rs index 182d2f6..5374806 100644 --- a/core/src/metadata/declarations/delegate_declaration/generic_delegate_instance_declaration.rs +++ b/core/src/metadata/declarations/delegate_declaration/generic_delegate_instance_declaration.rs @@ -1,75 +1,93 @@ use std::borrow::Cow; -use core_bindings::{mdTypeDef, mdTypeSpec, IMetaDataImport2}; +use core_bindings::{mdTypeDef, mdTypeSpec}; -use crate::bindings::{enums, imeta_data_import2}; +use crate::bindings::enums; use crate::enums::CorTokenType; use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; -use crate::metadata::declarations::delegate_declaration::{DelegateDeclaration, DelegateDeclarationImpl}; +use crate::metadata::declarations::delegate_declaration::{ + DelegateDeclaration, DelegateDeclarationImpl, +}; +use crate::metadata::declarations::method_declaration::MethodDeclaration; +use crate::metadata::declarations::type_declaration::TypeDeclaration; use crate::metadata::generic_instance_id_builder::GenericInstanceIdBuilder; use crate::metadata::signature::Signature; use crate::prelude::*; -use crate::metadata::declarations::method_declaration::MethodDeclaration; -use crate::metadata::declarations::type_declaration::TypeDeclaration; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, RwLock}; #[derive(Clone, Debug)] pub struct GenericDelegateInstanceDeclaration { - base: DelegateDeclaration, - closed_token: mdTypeSpec, - closed_metadata: Arc>, + base: DelegateDeclaration, + closed_token: mdTypeSpec, + closed_metadata: Option>>, } impl GenericDelegateInstanceDeclaration { - pub fn new(open_metadata: Arc>, open_token: mdTypeDef, closed_metadata: Arc>, closed_token: mdTypeSpec) -> Self { - debug_assert!(!closed_metadata.is_null()); - debug_assert!(CorTokenType::from(enums::type_from_token(closed_token)) == CorTokenType::mdtTypeSpec); - debug_assert!(closed_token != mdTypeSpecNil); + pub fn new( + open_metadata: Option>>, + open_token: mdTypeDef, + closed_metadata: Option>>, + closed_token: mdTypeSpec, + ) -> Self { + debug_assert!(closed_metadata.is_some()); + debug_assert!( + CorTokenType::from(enums::type_from_token(closed_token)) == CorTokenType::mdtTypeSpec + ); + debug_assert!(closed_token != mdTypeSpecNil); - Self { - base: DelegateDeclaration::new_overload( - DeclarationKind::GenericDelegateInstance, open_metadata, open_token, - ), - closed_token, - closed_metadata, - } - } + Self { + base: DelegateDeclaration::new_overload( + DeclarationKind::GenericDelegateInstance, + open_metadata, + open_token, + ), + closed_token, + closed_metadata, + } + } } impl Declaration for GenericDelegateInstanceDeclaration { - fn name<'b>(&self) -> Cow<'b, str> { - self.base.name() - } + fn name<'b>(&self) -> Cow<'b, str> { + self.base.name() + } - fn full_name<'b>(&self) -> Cow<'b, str> { - let mut signature = vec![0_u8; MAX_IDENTIFIER_LENGTH]; - let mut sig = signature.as_ptr(); - let mut signature_size = 0; - debug_assert!( - imeta_data_import2::get_type_spec_from_token( - self.closed_metadata, self.closed_token, &mut sig, &mut signature_size, - ).is_ok() - ); - signature.resize(signature_size as usize, 0); - Signature::to_string(self.closed_metadata, sig).into() - } + fn full_name<'b>(&self) -> Cow<'b, str> { + match Option::as_ref(&self.closed_metadata) { + None => Cow::default(), + Some(metadata) => { + if let Ok(metadata) = metadata.try_read() { + let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; + let mut sig = signature.as_ptr(); + let mut signature_size = 0; + let result = metadata.get_type_spec_from_token( + self.closed_token, + &mut sig, + &mut signature_size, + ); + debug_assert!(result.is_ok()); + signature.resize(signature_size as usize, 0); + Signature::to_string(&*metadata, sig).into() + } + } + } + } - fn kind(&self) -> DeclarationKind { - self.base.kind() - } + fn kind(&self) -> DeclarationKind { + self.base.kind() + } } - impl DelegateDeclarationImpl for GenericDelegateInstanceDeclaration { - fn base<'b>(&self) -> &'b TypeDeclaration { - &self.base.base - } + fn base<'b>(&self) -> &'b TypeDeclaration { + &self.base.base + } - fn id(&self) -> CLSID { - GenericInstanceIdBuilder::generate_id(self) - } + fn id(&self) -> CLSID { + GenericInstanceIdBuilder::generate_id(self) + } - fn invoke_method<'b>(&self) -> &MethodDeclaration<'b> { - &self.base.invoke_method - } -} \ No newline at end of file + fn invoke_method<'b>(&self) -> &MethodDeclaration { + &self.base.invoke_method + } +} diff --git a/core/src/metadata/declarations/delegate_declaration/mod.rs b/core/src/metadata/declarations/delegate_declaration/mod.rs index a6cc91c..52cacca 100644 --- a/core/src/metadata/declarations/delegate_declaration/mod.rs +++ b/core/src/metadata/declarations/delegate_declaration/mod.rs @@ -1,86 +1,99 @@ use std::borrow::Cow; use crate::{ - bindings::{imeta_data_import2}, - metadata::com_helpers::get_guid_attribute_value, - metadata::declarations::declaration::{Declaration, DeclarationKind}, - metadata::declarations::method_declaration::MethodDeclaration, - metadata::declarations::type_declaration::TypeDeclaration, - prelude::*, + metadata::com_helpers::get_guid_attribute_value, + metadata::declarations::declaration::{Declaration, DeclarationKind}, + metadata::declarations::method_declaration::MethodDeclaration, + metadata::declarations::type_declaration::TypeDeclaration, + prelude::*, }; -use std::sync::{Arc, Mutex}; - +use core_bindings::GUID; +use std::sync::{Arc, RwLock}; pub mod generic_delegate_declaration; pub mod generic_delegate_instance_declaration; const INVOKE_METHOD_NAME: &str = "Invoke"; -pub fn get_invoke_method_token(meta_data: *mut IMetaDataImport2, token: mdTypeDef) -> mdMethodDef { - let mut invoke_method_token = mdTokenNil; - let string = windows::HSTRING::from(INVOKE_METHOD_NAME); - debug_assert!( - imeta_data_import2::find_method( - meta_data, token, string.as_wide().as_ptr(), None, None, Some(&mut invoke_method_token), - ).is_ok() - ); - return invoke_method_token; +pub fn get_invoke_method_token( + metadata: Option>>, + token: mdTypeDef, +) -> mdMethodDef { + let mut invoke_method_token = mdTokenNil; + let string = windows::HSTRING::from(INVOKE_METHOD_NAME); + if let Some(metadata) = Option::as_ref(&metadata) { + if let Ok(metadata) = metadata.try_read() { + let result = metadata.find_method( + token, + string.as_wide().as_ptr(), + None, + None, + Some(&mut invoke_method_token), + ); + debug_assert!(result.is_ok()); + } + } + return invoke_method_token; } pub trait DelegateDeclarationImpl { - fn base(&self) -> &TypeDeclaration; - fn id(&self) -> GUID { - get_guid_attribute_value(self.base().metadata_mut(), self.base().token) - } - fn invoke_method(&self) -> &MethodDeclaration; + fn base(&self) -> &TypeDeclaration; + fn id(&self) -> GUID { + get_guid_attribute_value(self.base().metadata_mut(), self.base().token()) + } + fn invoke_method(&self) -> &MethodDeclaration; } #[derive(Clone, Debug)] pub struct DelegateDeclaration { - base: TypeDeclaration, - invoke_method: MethodDeclaration, + base: TypeDeclaration, + invoke_method: MethodDeclaration, } impl<'a> DelegateDeclaration { - pub fn new(metadata: Arc>, token: mdTypeDef) -> Self { - Self::new_overload( - DeclarationKind::Delegate, metadata, token, - ) - } + pub fn new(metadata: Option>>, token: mdTypeDef) -> Self { + Self::new_overload(DeclarationKind::Delegate, metadata, token) + } - pub fn new_overload(kind: DeclarationKind, metadata: Arc>, token: mdTypeDef) -> Self { - Self { - base: TypeDeclaration::new( - kind, metadata, token, - ), - invoke_method: MethodDeclaration::new( - metadata, get_invoke_method_token(metadata, token), - ), - } - } + pub fn new_overload( + kind: DeclarationKind, + metadata: Option>>, + token: mdTypeDef, + ) -> Self { + Self { + base: TypeDeclaration::new( + kind, + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + invoke_method: MethodDeclaration::new( + metadata, + get_invoke_method_token(Option::as_ref(&metadata).map(|v| Arc::clone(v)), token), + ), + } + } } impl Declaration for DelegateDeclaration { - fn name<'b>(&self) -> Cow<'b, str> { - self.base.name() - } + fn name<'b>(&self) -> Cow<'b, str> { + self.base.name() + } - fn full_name<'b>(&self) -> Cow<'b, str> { - self.base.full_name() - } + fn full_name<'b>(&self) -> Cow<'b, str> { + self.base.full_name() + } - fn kind(&self) -> DeclarationKind { - self.base.kind - } + fn kind(&self) -> DeclarationKind { + self.base.kind() + } } - impl DelegateDeclarationImpl for DelegateDeclaration { - fn base<'b>(&self) -> &'b TypeDeclaration { - &self.base - } + fn base<'b>(&self) -> &'b TypeDeclaration { + &self.base + } - fn invoke_method<'b>(&self) -> &'b MethodDeclaration { - &self.invoke_method - } -} \ No newline at end of file + fn invoke_method<'b>(&self) -> &'b MethodDeclaration { + &self.invoke_method + } +} diff --git a/core/src/metadata/declarations/enum_declaration.rs b/core/src/metadata/declarations/enum_declaration.rs index c1b1831..d9cf059 100644 --- a/core/src/metadata/declarations/enum_declaration.rs +++ b/core/src/metadata/declarations/enum_declaration.rs @@ -1,6 +1,6 @@ use crate::prelude::*; use crate::bindings::{ - imeta_data_import2, helpers, + helpers, }; use super::{ declaration::{ @@ -10,7 +10,7 @@ use super::{ type_declaration::TypeDeclaration, }; use std::borrow::Cow; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, RwLock}; #[derive(Debug)] pub struct EnumDeclaration { @@ -31,12 +31,12 @@ impl Declaration for EnumDeclaration { } fn kind(&self) -> DeclarationKind { - self.base.kind + self.base.kind() } } impl EnumDeclaration { - pub fn new(metadata: Arc>, token: mdTypeDef) -> Self { + pub fn new(metadata: Option>>, token: mdTypeDef) -> Self { Self { base: TypeDeclaration::new(DeclarationKind::Enum, metadata, token) } @@ -45,30 +45,36 @@ impl EnumDeclaration { pub fn type_<'b>(&self) -> Cow<'b, &[u8]> { let mut type_field = mdTokenNil; let name_w = OsString::from(COR_ENUM_FIELD_NAME).to_wide(); - debug_assert!(imeta_data_import2::find_field( - self.base.metadata_mut(), self.base.token, - Some(name_w.as_ptr()), None, None, Some(&mut type_field), - ).is_ok()); - let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; - let mut signature_size = 0; - debug_assert!( - imeta_data_import2::get_field_props( - self.base.metadata_mut(), - type_field, - None, None, None, None, None, - Some(&mut signature.as_mut_ptr() as _ as *mut *const u8), - Some(&mut signature_size), - None, None, None, - ).is_ok() - ); + match self.base.metadata() { + None => Cow::default(), + Some(metadata) => { + let result = metadata.find_field( + self.base.token(), + Some(name_w.as_ptr()), None, None, Some(&mut type_field), + ); + debug_assert!(result.is_ok()); + let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; + let mut signature_size = 0; + metadata.get_field_props( + type_field, + None, None, None, None, None, + Some(&mut signature.as_mut_ptr() as _ as *mut *const u8), + Some(&mut signature_size), + None, None, None, + ); + debug_assert!( + result.is_ok() + ); - let header = helpers::cor_sig_uncompress_data(signature.as_ptr()); - debug_assert!( - header == CorCallingConvention::ImageCeeCsCallconvField as u32 - ); + let header = helpers::cor_sig_uncompress_data(signature.as_ptr()); + debug_assert!( + header == CorCallingConvention::ImageCeeCsCallconvField as u32 + ); - let result: &[u8] = &signature[0..signature_size]; + let result: &[u8] = &signature[0..signature_size]; - result.into() + result.into() + } + } } } \ No newline at end of file diff --git a/core/src/metadata/declarations/event_declaration.rs b/core/src/metadata/declarations/event_declaration.rs index 1015bad..a849082 100644 --- a/core/src/metadata/declarations/event_declaration.rs +++ b/core/src/metadata/declarations/event_declaration.rs @@ -1,128 +1,231 @@ -use crate::prelude::*; -use crate::bindings::{imeta_data_import2, helpers}; +use crate::bindings::{helpers}; +use crate::metadata::declaration_factory::DeclarationFactory; use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; -use crate::metadata::declarations::type_declaration::TypeDeclaration; -use crate::metadata::declarations::delegate_declaration::DelegateDeclaration; +use crate::metadata::declarations::delegate_declaration::{ + DelegateDeclaration, DelegateDeclarationImpl, +}; use crate::metadata::declarations::method_declaration::MethodDeclaration; -use std::ffi::c_void; -use crate::metadata::declaration_factory::DeclarationFactory; +use crate::metadata::declarations::type_declaration::TypeDeclaration; +use crate::prelude::*; use std::borrow::Cow; +use std::sync::{Arc, RwLock}; #[derive(Clone, Debug)] -pub struct EventDeclaration<'a> { - base: TypeDeclaration<'a>, - // Arc ?? - type_: DelegateDeclaration<'a>, - add_method: MethodDeclaration<'a>, - remove_method: MethodDeclaration<'a>, +pub struct EventDeclaration { + base: TypeDeclaration, + // Arc ?? + type_: Option>>, + add_method: MethodDeclaration, + remove_method: MethodDeclaration, } -impl<'a> EventDeclaration <'a> { - pub fn make_add_method<'b>(metadata: *mut c_void, token: mdEvent) -> MethodDeclaration<'b> { - let mut add_method_token = mdTokenNil; - debug_assert!( - imeta_data_import2::get_event_props( - metadata, token, None, None, None, - None, None, None, Some(&mut add_method_token), - None, None, None, None, None, - ).is_ok() - ); - MethodDeclaration::new(metadata, add_method_token) - } - - pub fn make_remove_method<'b>(metadata: *mut c_void, token: mdEvent) -> MethodDeclaration<'b> { - let mut remove_method_token = mdTokenNil; - debug_assert!( - imeta_data_import2::get_event_props( - metadata, token, None, None, None, - None, None, None, None, - Some(&mut remove_method_token), None, None, None, - None, - ) - ); - - MethodDeclaration::new(metadata, remove_method_token) - } - - pub fn make_type<'b>(metadata: *mut c_void, token: mdEvent) -> DelegateDeclaration<'b> { - let mut delegate_token = mdTokenNil; - debug_assert!( - imeta_data_import2::get_event_props( - metadata, token, None, None, None, None, None, - Some(&mut delegate_token), None, None, None, None, None, None, - ).is_ok() - ); - return DeclarationFactory::make_delegate_declaration(metadata, delegate_token); - } - - pub fn new(metadata: *mut c_void, token: mdEvent) -> Self { - Self { - base: TypeDeclaration::new(DeclarationKind::Event, metadata, token), - type_: EventDeclaration::make_type(metadata, token), - add_method: EventDeclaration::make_add_method(metadata, token), - remove_method: EventDeclaration::make_remove_method(metadata, token), - } - } - - pub fn is_static(&self) -> bool { - self.add_method.is_static() - } - - pub fn is_sealed(&self) -> bool { - self.add_method.is_sealed() - } - - pub fn type_(&self) -> &DelegateDeclaration { - &self.type_ - } - - pub fn add_method(&self) -> &MethodDeclaration { - &self.add_method - } - - pub fn remove_method(&self) -> &MethodDeclaration { - &self.remove_method - } +impl EventDeclaration { + pub fn make_add_method( + metadata: Option>>, + token: mdEvent, + ) -> MethodDeclaration { + let mut add_method_token = mdTokenNil; + if let Some(metadata) = Option::as_ref(&metadata) { + match metadata.try_read() { + Ok(metadata) => { + let result = metadata.get_event_props( + token, + None, + None, + None, + None, + None, + None, + Some(&mut add_method_token), + None, + None, + None, + None, + None, + ); + debug_assert!(result.is_ok()); + } + Err(_) => {} + } + } + MethodDeclaration::new( + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + add_method_token, + ) + } + + pub fn make_remove_method( + metadata: Option>>, + token: mdEvent, + ) -> MethodDeclaration { + let mut remove_method_token = mdTokenNil; + match Option::as_ref(&metadata) { + None => {} + Some(metadata) => match metadata.try_read() { + Ok(metadata) => { + let result = metadata.get_event_props( + token, + None, + None, + None, + None, + None, + None, + None, + Some(&mut remove_method_token), + None, + None, + None, + None, + ); + + debug_assert!(result.is_ok()); + } + Err(_) => {} + }, + } + MethodDeclaration::new( + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + remove_method_token, + ) + } + + pub fn make_type( + metadata: Option>>, + token: mdEvent, + ) -> Option>> { + let mut delegate_token = mdTokenNil; + match Option::as_ref(&metadata) { + None => {} + Some(metadata) => match metadata.try_read() { + Ok(metadata) => { + let result = metadata.get_event_props( + token, + None, + None, + None, + None, + None, + Some(&mut delegate_token), + None, + None, + None, + None, + None, + None, + ); + debug_assert!(result.is_ok()); + } + Err(_) => {} + }, + } + return DeclarationFactory::make_delegate_declaration( + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + delegate_token, + ); + } + + pub fn new(metadata: Option>>, token: mdEvent) -> Self { + Self { + base: TypeDeclaration::new( + DeclarationKind::Event, + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + type_: EventDeclaration::make_type( + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + add_method: EventDeclaration::make_add_method( + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + remove_method: EventDeclaration::make_remove_method( + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + } + } + + pub fn is_static(&self) -> bool { + self.add_method.is_static() + } + + pub fn is_sealed(&self) -> bool { + self.add_method.is_sealed() + } + + pub fn type_(&self) -> &DelegateDeclaration { + &self.type_ + } + + pub fn add_method(&self) -> &MethodDeclaration { + &self.add_method + } + + pub fn remove_method(&self) -> &MethodDeclaration { + &self.remove_method + } } -impl<'a> Declaration for EventDeclaration<'a> { - fn is_exported(&self) -> bool { - let mut flags = 0; - debug_assert!( - imeta_data_import2::get_event_props( - self.base.metadata, self.base.token, - None, None, None, None, - Some(&mut flags), None, None, - None, None, None, None, None, - ).is_ok() - ); - if helpers::is_ev_special_name(flags) { - return false; - } - - return true; - } - - fn name<'b>(&self) -> Cow<'b, str> { - self.full_name() - } - - fn full_name<'b>(&self) -> Cow<'b, str> { - let mut name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; - let mut name_data_length = 0; - - debug_assert!( - imeta_data_import2::get_event_props( - self.base.metadata, self.base.token, - None, Some(name_data.as_mut_ptr()), Some(name_data.len() as u32), - Some(&mut name_data_length), None, None, None, - None, None, None, None, None, - ).is_ok() - ); - OsString::from_wide(&name_data[..name_data_length]).into() - } - - fn kind(&self) -> DeclarationKind { - self.base.kind - } -} \ No newline at end of file +impl Declaration for EventDeclaration { + fn is_exported(&self) -> bool { + let mut flags = 0; + if let Some(metadata) = self.base.metadata() { + let result = metadata.get_event_props( + self.base.token(), + None, + None, + None, + None, + Some(&mut flags), + None, + None, + None, + None, + None, + None, + None, + ); + debug_assert!(result.is_ok()); + } + if helpers::is_ev_special_name(flags) { + return false; + } + + return true; + } + + fn name<'b>(&self) -> Cow<'b, str> { + self.full_name() + } + + fn full_name<'b>(&self) -> Cow<'b, str> { + let mut name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; + let mut name_data_length = 0; + + if let Some(metadata) = self.base.metadata() { + let result = metadata.get_event_props( + self.base.token(), + None, + Some(name_data.as_mut_ptr()), + Some(name_data.len() as u32), + Some(&mut name_data_length), + None, + None, + None, + None, + None, + None, + None, + None, + ); + debug_assert!(result.is_ok()); + } + OsString::from_wide(&name_data[..name_data_length]).into() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind() + } +} diff --git a/core/src/metadata/declarations/field_declaration.rs b/core/src/metadata/declarations/field_declaration.rs index 1960889..252fab1 100644 --- a/core/src/metadata/declarations/field_declaration.rs +++ b/core/src/metadata/declarations/field_declaration.rs @@ -1,62 +1,90 @@ use super::declaration::{Declaration, DeclarationKind}; use crate::prelude::*; -use crate::bindings::{ - imeta_data_import2, - enums, -}; -use std::{ - marker, - ffi::{OsString}, - borrow::Cow, -}; +use crate::bindings::enums; +use std::sync::{Arc, RwLock}; +use std::{borrow::Cow, ffi::OsString}; #[derive(Clone, Debug)] -pub struct FieldDeclaration<'a> { - pub kind: DeclarationKind, - pub metadata: *mut c_void, - pub token: mdFieldDef, - _marker: marker::PhantomData<&'a *const c_void>, +pub struct FieldDeclaration { + kind: DeclarationKind, + metadata: Option>>, + token: mdFieldDef, } -impl<'a> Declaration for FieldDeclaration<'a> { - fn name<'b>(&self) -> Cow<'b, str> { - return self.full_name(); - } - - fn full_name<'b>(&self) -> Cow<'b, str> { - let mut full_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; - let mut length = 0; - debug_assert!(imeta_data_import2::get_field_props( - self.metadata, self.token, None, - Some(full_name_data.as_mut_ptr()), - Some(full_name_data.len() as u32), - Some(&mut length), - None, None, - None, None, - None, None, - ).is_ok()); - - OsString::from_wide(full_name_data[..length]).into() - } - - fn kind(&self) -> DeclarationKind { - self.kind - } +impl Declaration for FieldDeclaration { + fn name<'b>(&self) -> Cow<'b, str> { + return self.full_name(); + } + + fn full_name<'b>(&self) -> Cow<'b, str> { + match self.metadata() { + None => Cow::default(), + Some(metadata) => { + let mut full_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; + let mut length = 0; + let result = metadata.get_field_props( + self.token, + None, + Some(&mut full_name_data), + Some(full_name_data.len() as u32), + Some(&mut length), + None, + None, + None, + None, + None, + None, + ); + + debug_assert!(result.is_ok()); + + OsString::from_wide(full_name_data[..length]).into() + } + } + } + + fn kind(&self) -> DeclarationKind { + self.kind + } } -impl<'a> FieldDeclaration<'a> { - pub fn new(kind: DeclarationKind, metadata: *mut c_void, token: mdFieldDef) -> Self { - let value = Self { - kind, - metadata, - token, - _marker: marker::PhantomData, - }; - - assert!(value.metadata.is_not_null()); - assert!(enums::type_from_token(value.token) == CorTokenType::mdtFieldDef as u32); - assert!(value.token != mdFieldDefNil); - value - } -} \ No newline at end of file +impl FieldDeclaration { + pub fn metadata_mut<'a>(&mut self) -> Option<&'a mut IMetaDataImport2> { + Option::as_mut(&mut self.metadata).map(|v| match v.try_read() { + Ok(val) => &mut *val, + Err(_) => None, + }) + } + + pub fn metadata<'a>(&self) -> Option<&'a IMetaDataImport2> { + Option::as_ref(&self.metadata).map(|v| match v.try_read() { + Ok(val) => &mut *val, + Err(_) => None, + }) + } + + pub fn kind(&self) -> DeclarationKind { + self.kind + } + + pub fn token(&self) -> mdFieldDef { + self.token + } + pub fn new( + kind: DeclarationKind, + metadata: Option>>, + token: mdFieldDef, + ) -> Self { + { + debug_assert!(metadata.is_none()); + debug_assert!(enums::type_from_token(token) == CorTokenType::mdtFieldDef as u32); + debug_assert!(token != mdFieldDefNil); + } + Self { + kind, + metadata, + token, + } + } +} diff --git a/core/src/metadata/declarations/interface_declaration/generic_interface_declaration.rs b/core/src/metadata/declarations/interface_declaration/generic_interface_declaration.rs index 35419e8..016e0c6 100644 --- a/core/src/metadata/declarations/interface_declaration/generic_interface_declaration.rs +++ b/core/src/metadata/declarations/interface_declaration/generic_interface_declaration.rs @@ -1,83 +1,92 @@ use std::borrow::Cow; -use core_bindings::{GUID, mdToken, IMetaDataImport2}; - -use crate::bindings::imeta_data_import2; use crate::metadata::declarations::base_class_declaration::BaseClassDeclarationImpl; use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; use crate::metadata::declarations::event_declaration::EventDeclaration; +use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; use crate::metadata::declarations::method_declaration::MethodDeclaration; use crate::metadata::declarations::property_declaration::PropertyDeclaration; use crate::metadata::declarations::type_declaration::TypeDeclaration; -use crate::prelude::c_void; -use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; +use crate::prelude::*; +use core_bindings::{mdToken, GUID}; +use std::sync::{Arc, RwLock}; #[derive(Clone, Debug)] -pub struct GenericInterfaceDeclaration<'a> { - base: InterfaceDeclaration<'a>, +pub struct GenericInterfaceDeclaration { + base: InterfaceDeclaration, } -impl<'a> GenericInterfaceDeclaration<'a> { - pub fn new(metadata: *mut IMetaDataImport2, token: mdToken) -> Self { - Self { - base: InterfaceDeclaration::new_with_kind(DeclarationKind::GenericInterface, metadata, token) - } - } - - pub fn number_of_generic_parameters(&self) -> usize { - let mut count = 0; - let mut enumerator = std::ptr::null_mut(); - let enumerator_ptr = &mut enumerator; - let base = self.base.base.base(); - debug_assert!( - imeta_data_import2::enum_generic_params( - base.metadata, enumerator_ptr, base.token, None, None, None, - ).is_ok() - ); - debug_assert!( - imeta_data_import2::count_enum(base.metadata, enumerator, &mut count).is_ok() - ); +impl GenericInterfaceDeclaration { + pub fn new(metadata: Option>>, token: mdToken) -> Self { + Self { + base: InterfaceDeclaration::new_with_kind( + DeclarationKind::GenericInterface, + metadata, + token, + ), + } + } - return count as usize; - } + pub fn number_of_generic_parameters(&self) -> usize { + let mut count = 0; + let mut enumerator = std::ptr::null_mut(); + let enumerator_ptr = &mut enumerator; + let base = self.base(); + match self.base().metadata() { + None => {} + Some(metadata) => { + let result_1 = + metadata.enum_generic_params(enumerator_ptr, base.token(), None, None, None); + debug_assert!(result_1.is_ok()); + let result_2 = metadata.count_enum(enumerator, &mut count); + debug_assert!(result_2.is_ok()); + let result_1 = + metadata.enum_generic_params(enumerator_ptr, base.token(), None, None, None); + debug_assert!(result_1.is_ok()); + let result_2 = metadata.count_enum(enumerator, &mut count); + debug_assert!(result_2.is_ok()); + } + } + return count as usize; + } - pub fn id(&self) -> GUID { - self.base.id() - } + pub fn id(&self) -> GUID { + self.base.id() + } } -impl<'a> BaseClassDeclarationImpl for GenericInterfaceDeclaration<'a> { - fn base(&self) -> &TypeDeclaration { - self.base.base() - } +impl BaseClassDeclarationImpl for GenericInterfaceDeclaration { + fn base(&self) -> &TypeDeclaration { + self.base.base() + } - fn implemented_interfaces(&self) -> &Vec { - self.base.implemented_interfaces() - } + fn implemented_interfaces(&self) -> &Vec { + self.base.implemented_interfaces() + } - fn methods(&self) -> &Vec { - self.base.methods() - } + fn methods(&self) -> &[MethodDeclaration] { + self.base.methods() + } - fn properties(&self) -> &Vec { - self.base.properties() - } + fn properties(&self) -> &[PropertyDeclaration] { + self.base.properties() + } - fn events(&self) -> &Vec { - self.base.events() - } + fn events(&self) -> &[EventDeclaration] { + self.base.events() + } } -impl<'a> Declaration for GenericInterfaceDeclaration<'a> { - fn name<'b>(&self) -> Cow<'b, str> { - self.base.name() - } +impl Declaration for GenericInterfaceDeclaration { + fn name<'b>(&self) -> Cow<'b, str> { + self.base.name() + } - fn full_name<'b>(&self) -> Cow<'b, str> { - self.base.full_name() - } + fn full_name<'b>(&self) -> Cow<'b, str> { + self.base.full_name() + } - fn kind(&self) -> DeclarationKind { - self.base.kind() - } + fn kind(&self) -> DeclarationKind { + self.base.kind() + } } diff --git a/core/src/metadata/declarations/interface_declaration/generic_interface_instance_declaration.rs b/core/src/metadata/declarations/interface_declaration/generic_interface_instance_declaration.rs index 180a018..844a77b 100644 --- a/core/src/metadata/declarations/interface_declaration/generic_interface_instance_declaration.rs +++ b/core/src/metadata/declarations/interface_declaration/generic_interface_instance_declaration.rs @@ -1,90 +1,108 @@ use std::borrow::Cow; -use core_bindings::{GUID, mdTypeDef, mdTypeSpec}; +use core_bindings::{mdTypeDef, mdTypeSpec, GUID}; use crate::{ - metadata::declarations::method_declaration::MethodDeclaration, - metadata::declarations::event_declaration::EventDeclaration, - metadata::declarations::declaration::{Declaration, DeclarationKind}, - metadata::declarations::base_class_declaration::BaseClassDeclarationImpl, - enums::CorTokenType, - bindings::{enums, imeta_data_import2}, - metadata::declarations::property_declaration::PropertyDeclaration, - metadata::declarations::type_declaration::TypeDeclaration, - metadata::generic_instance_id_builder::GenericInstanceIdBuilder, - metadata::signature::Signature, - prelude::*, - metadata::declarations::interface_declaration::InterfaceDeclaration + bindings::enums, + enums::CorTokenType, + metadata::declarations::base_class_declaration::BaseClassDeclarationImpl, + metadata::declarations::declaration::{Declaration, DeclarationKind}, + metadata::declarations::event_declaration::EventDeclaration, + metadata::declarations::interface_declaration::InterfaceDeclaration, + metadata::declarations::method_declaration::MethodDeclaration, + metadata::declarations::property_declaration::PropertyDeclaration, + metadata::declarations::type_declaration::TypeDeclaration, + metadata::generic_instance_id_builder::GenericInstanceIdBuilder, + metadata::signature::Signature, + prelude::*, }; +use std::sync::{Arc, RwLock}; #[derive(Clone, Debug)] -pub struct GenericInterfaceInstanceDeclaration<'a> { - base: InterfaceDeclaration<'a>, - closed_metadata: *mut c_void, - closed_token: mdTypeSpec, +pub struct GenericInterfaceInstanceDeclaration { + base: InterfaceDeclaration, + closed_metadata: Option>>, + closed_token: mdTypeSpec, } -impl<'a> GenericInterfaceInstanceDeclaration<'a> { - pub fn new(open_metadata: *mut IMetaDataImport2, open_token: mdTypeDef, closed_metadata: *mut c_void, closed_token: mdTypeSpec) -> Self { - debug_assert!(!closed_metadata.is_null()); - debug_assert!(CorTokenType::from(enums::type_from_token(closed_token)) == CorTokenType::mdtTypeSpec); - debug_assert!(closed_token != mdTypeSpecNil); +impl GenericInterfaceInstanceDeclaration { + pub fn new( + open_metadata: Option>>, + open_token: mdTypeDef, + closed_metadata: Option>>, + closed_token: mdTypeSpec, + ) -> Self { + debug_assert!(closed_metadata.is_none()); + debug_assert!( + CorTokenType::from(enums::type_from_token(closed_token)) == CorTokenType::mdtTypeSpec + ); + debug_assert!(closed_token != mdTypeSpecNil); - Self { - base: InterfaceDeclaration::new_with_kind( - DeclarationKind::GenericInterfaceInstance, open_metadata, open_token, - ), - closed_metadata, - closed_token, - } - } - pub fn id(&self) -> GUID { - return GenericInstanceIdBuilder::generate_id(self); - } + Self { + base: InterfaceDeclaration::new_with_kind( + DeclarationKind::GenericInterfaceInstance, + open_metadata, + open_token, + ), + closed_metadata, + closed_token, + } + } + pub fn id(&self) -> GUID { + return GenericInstanceIdBuilder::generate_id(self); + } } -impl<'a> BaseClassDeclarationImpl for GenericInterfaceInstanceDeclaration<'a> { - fn base(&self) -> &TypeDeclaration { - self.base.base() - } +impl BaseClassDeclarationImpl for GenericInterfaceInstanceDeclaration { + fn base(&self) -> &TypeDeclaration { + self.base.base() + } - fn implemented_interfaces(&self) -> &Vec { - self.base.implemented_interfaces() - } + fn implemented_interfaces(&self) -> &[InterfaceDeclaration] { + self.base.implemented_interfaces() + } - fn methods(&self) -> &Vec { - self.base.methods() - } + fn methods(&self) -> &[MethodDeclaration] { + self.base.methods() + } - fn properties(&self) -> &Vec { - self.base.properties() - } + fn properties(&self) -> &[PropertyDeclaration] { + self.base.properties() + } - fn events(&self) -> &Vec { - self.base.events() - } + fn events(&self) -> &[EventDeclaration] { + self.base.events() + } } -impl<'a> Declaration for GenericInterfaceInstanceDeclaration<'a> { - fn name<'b>(&self) -> Cow<'b, str> { - self.base.name() - } +impl Declaration for GenericInterfaceInstanceDeclaration { + fn name<'b>(&self) -> Cow<'b, str> { + self.base.name() + } - fn full_name<'b>(&self) -> Cow<'b, str> { - let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; - let signature_ptr = &mut signature.as_ptr(); - let mut signature_size = 0; - debug_assert!( - imeta_data_import2::get_type_spec_from_token( - self.closed_metadata, self.closed_token, signature_ptr, &mut signature_size, - ).is_ok() - ); - Signature::to_string( - self.closed_metadata, signature.as_ptr(), - ).into() - } + fn full_name<'b>(&self) -> Cow<'b, str> { + let mut signature = std::mem::MaybeUninit::uninit(); + //let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; + let signature_ptr = &mut signature.as_mut_ptr(); + let mut signature_size = 0; + match Option::as_ref(&self.closed_metadata) { + None => Cow::default(), + Some(metadata) => match metadata.try_read() { + Ok(metadata) => { + let result = metadata.get_type_spec_from_token( + self.closed_token, + signature_ptr as _, + &mut signature_size, + ); + debug_assert!(result.is_ok()); + Signature::to_string(&metadata, signature.as_ptr()).into() + } + Err(_) => Cow::default(), + }, + } + } - fn kind(&self) -> DeclarationKind { - self.base.kind() - } + fn kind(&self) -> DeclarationKind { + self.base.kind() + } } diff --git a/core/src/metadata/declarations/interface_declaration/mod.rs b/core/src/metadata/declarations/interface_declaration/mod.rs index 3663fdc..36a678d 100644 --- a/core/src/metadata/declarations/interface_declaration/mod.rs +++ b/core/src/metadata/declarations/interface_declaration/mod.rs @@ -1,8 +1,9 @@ use std::borrow::Cow; - use crate::metadata::com_helpers::get_guid_attribute_value; -use crate::metadata::declarations::base_class_declaration::{BaseClassDeclaration, BaseClassDeclarationImpl}; +use crate::metadata::declarations::base_class_declaration::{ + BaseClassDeclaration, BaseClassDeclarationImpl, +}; use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; use crate::metadata::declarations::event_declaration::EventDeclaration; use crate::metadata::declarations::method_declaration::MethodDeclaration; @@ -10,71 +11,70 @@ use crate::metadata::declarations::property_declaration::PropertyDeclaration; use crate::metadata::declarations::type_declaration::TypeDeclaration; use crate::prelude::*; -pub mod generic_interface_instance_declaration; pub mod generic_interface_declaration; +pub mod generic_interface_instance_declaration; - -use core_bindings::{GUID, mdToken}; - +use core_bindings::{mdToken, GUID}; +use std::sync::{Arc, RwLock}; #[derive(Clone, Debug)] -pub struct InterfaceDeclaration<'a> { - base: BaseClassDeclaration<'a>, +pub struct InterfaceDeclaration { + base: BaseClassDeclaration, } -impl<'a> InterfaceDeclaration<'a> { - pub fn new(metadata: *mut IMetaDataImport2, token: mdToken) -> Self { - Self::new_with_kind( - DeclarationKind::Interface, metadata, token, - ) - } - - pub fn new_with_kind(kind: DeclarationKind, metadata: *mut IMetaDataImport2, token: mdToken) -> Self { - Self { - base: BaseClassDeclaration::new( - kind, metadata, token, - ) - } - } - - pub fn id(&self) -> GUID { - let base = self.base.base(); - get_guid_attribute_value(base.metadata, base.token) - } +impl InterfaceDeclaration { + pub fn new(metadata: Option>>, token: mdToken) -> Self { + Self::new_with_kind(DeclarationKind::Interface, metadata, token) + } + + pub fn new_with_kind( + kind: DeclarationKind, + metadata: Option>>, + token: mdToken, + ) -> Self { + Self { + base: BaseClassDeclaration::new(kind, metadata, token), + } + } + + pub fn id(&self) -> GUID { + let base = self.base.base(); + get_guid_attribute_value(base.metadata(), base.token()) + } } -impl<'a> Declaration for InterfaceDeclaration<'a> { - fn name<'b>(&self) -> Cow<'b, str> { - self.base.name() - } +impl Declaration for InterfaceDeclaration { + fn name<'b>(&self) -> Cow<'b, str> { + self.base.name() + } - fn full_name<'b>(&self) -> Cow<'b, str> { - self.base.full_name() - } + fn full_name<'b>(&self) -> Cow<'b, str> { + self.base.full_name() + } - fn kind(&self) -> DeclarationKind { - self.base.kind() - } + fn kind(&self) -> DeclarationKind { + self.base.kind() + } } -impl<'a> BaseClassDeclarationImpl for InterfaceDeclaration<'a> { - fn base(&self) -> &TypeDeclaration { - self.base.base() - } +impl BaseClassDeclarationImpl for InterfaceDeclaration { + fn base(&self) -> &TypeDeclaration { + self.base.base() + } - fn implemented_interfaces(&self) -> &Vec { - self.base.implemented_interfaces() - } + fn implemented_interfaces(&self) -> &Vec { + self.base.implemented_interfaces() + } - fn methods(&self) -> &Vec { - self.base.methods() - } + fn methods(&self) -> &[MethodDeclaration] { + self.base.methods() + } - fn properties(&self) -> &Vec { - self.base.properties() - } + fn properties(&self) -> &[PropertyDeclaration] { + self.base.properties() + } - fn events(&self) -> &Vec { - self.base.events() - } + fn events(&self) -> &[EventDeclaration] { + self.base.events() + } } diff --git a/core/src/metadata/declarations/method_declaration.rs b/core/src/metadata/declarations/method_declaration.rs index 726d65f..65c7fb9 100644 --- a/core/src/metadata/declarations/method_declaration.rs +++ b/core/src/metadata/declarations/method_declaration.rs @@ -1,201 +1,276 @@ -use crate::{ - bindings::enums, - bindings::helpers, - bindings::imeta_data_import2, - metadata::declarations::declaration::{Declaration, DeclarationKind}, - metadata::declarations::type_declaration::TypeDeclaration, - metadata::signature::Signature, - prelude::* -}; use crate::enums::CorCallingConvention; use crate::metadata::com_helpers::get_unary_custom_attribute_string_value; use crate::metadata::declarations::parameter_declaration::ParameterDeclaration; +use crate::{ + bindings::enums, + bindings::helpers, + metadata::declarations::declaration::{Declaration, DeclarationKind}, + metadata::declarations::type_declaration::TypeDeclaration, + metadata::signature::Signature, + prelude::*, +}; use std::borrow::Cow; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, RwLock}; #[derive(Clone, Debug)] pub struct MethodDeclaration { - base: TypeDeclaration, - parameters: Vec, + base: TypeDeclaration, + parameters: Vec, + return_type: *const u8, } const OVERLOAD_ATTRIBUTE: &str = "Windows.Foundation.Metadata.OverloadAttribute"; -const DEFAULT_OVERLOAD_ATTRIBUTE: &str ="Windows.Foundation.Metadata.DefaultOverloadAttribute"; +const DEFAULT_OVERLOAD_ATTRIBUTE: &str = "Windows.Foundation.Metadata.DefaultOverloadAttribute"; impl MethodDeclaration { - pub fn base <'b>(&self) -> &'b TypeDeclaration { - &self.base - } - pub fn new(metadata: Arc>, token: mdMethodDef) -> Self { - debug_assert!(!metadata.is_null()); - debug_assert!(enums::type_from_token(token) == CorTokenType::mdtMethodDef as u32); - assert!(token != mdMethodDefNil); - - - let mut signature = std::mem::MaybeUninit::uninit(); - let mut signature_ptr = &mut signature.as_mut_ptr(); - let mut signature_size: ULONG = 0; - - - debug_assert!( - imeta_data_import2::get_method_props( - metadata, token, None, None, None, - None,None,Some(signature_ptr as *mut *const u8), Some(&mut signature_size), - None,None - ).is_ok() - ); - - - /* - #if _DEBUG - PCCOR_SIGNATURE startSignature{ signature }; -#endif - */ - - - if helpers::cor_sig_uncompress_calling_conv(signature as _) == CorCallingConvention::ImageCeeCsCallconvGeneric as u32 { - std::unimplemented!() - } - - let mut arguments_count = { helpers::cor_sig_uncompress_data(signature.as_ptr()) }; - - let return_type = Signature::consume_type(signature.as_ptr()); - - let mut parameters: Vec = Vec::new(); - let mut parameter_enumerator = std::mem::MaybeUninit::uninit(); - let enumerator = &mut parameter_enumerator; - let mut parameters_count: ULONG = 0; - let mut parameter_tokens: Vec = vec![0; 1024]; - - debug_assert!(imeta_data_import2::enum_params(metadata, enumerator, token, parameter_tokens.as_mut_ptr(), parameter_tokens.len() as u32,&mut parameters_count).is_ok()); - debug_assert!(parameters_count < (parameter_tokens.len() - 1) as u32); - - imeta_data_import2::close_enum(metadata, parameter_enumerator); - - let mut start_index = 0_usize; - - if arguments_count + 1 == parameters_count { - start_index += 1; - } - - for i in start_index..parameters_count as usize{ - let sig_type = Signature::consume_type(signature as *const u8); - parameters.push( - ParameterDeclaration::new( - metadata, parameter_tokens[i], sig_type - ) - ) - } - - // todo - //debug_assert!(signature_size == signature); - //debug_assert!(start_signature + signature_size == signature); - - Self { - base: TypeDeclaration::new(DeclarationKind::Method, metadata, token), - parameters - } - } - - pub fn is_initializer(&self) -> bool{ - let mut full_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; - let mut method_flags = 0; - assert!( - imeta_data_import2::get_method_props( - self.base.metadata, self.base.token, - None, - Some(full_name_data.as_mut_ptr()), Some(full_name_data.len() as u32), - None, Some(&mut method_flags), None, None, None, None - ).is_ok() - ); - - helpers::is_md_instance_initializer_w(method_flags, full_name_data.as_ptr()) - } - - pub fn is_static(&self) -> bool { - let mut method_flags = 0; - assert!( - imeta_data_import2::get_method_props( - self.base.metadata, self.base.token, None, - None, None, None,Some(&mut method_flags), - None, None, None, None - ).is_ok() - ); - helpers::is_md_static(method_flags) - } - - pub fn is_sealed(&self) -> bool { - let mut method_flags = 0; - assert!( - imeta_data_import2::get_method_props( - self.base.metadata, self.base.token, None, - None, None, None,Some(&mut method_flags), - None, None, None, None - ).is_ok() - ); - helpers::is_md_static(method_flags) || helpers::is_md_final(method_flags) - } - - pub fn parameters(&self) -> &Vec { - &self.parameters - } - - pub fn number_of_parameters(&self) -> usize{ - self.parameters.len() - } - - pub fn overload_name<'b>(&self) -> Cow<'b, str> { - get_unary_custom_attribute_string_value(self.base.metadata, self.base.token, OVERLOAD_ATTRIBUTE) - } - - pub fn is_default_overload(&self) -> bool { - let data = windows::HSTRING::from(DEFAULT_OVERLOAD_ATTRIBUTE).as_wide(); - let get_attribute_result = imeta_data_import2::get_custom_attribute_by_name( - self.base.metadata, self.base.token, Some(data.as_ptr()),None,None - ); - debug_assert!(get_attribute_result.is_ok()); -return get_attribute_result.0 == 0; -} + pub fn base<'b>(&self) -> &'b TypeDeclaration { + &self.base + } + pub fn new(metadata: Option>>, token: mdMethodDef) -> Self { + debug_assert!(metadata.is_none()); + debug_assert!( + CorTokenType::from(enums::type_from_token(token)) == CorTokenType::mdtMethodDef + ); + debug_assert!(token != mdMethodDefNil); + + let mut parameters: Vec = Vec::new(); + + let mut signature = std::mem::MaybeUninit::uninit(); + let mut signature_ptr = &mut signature.as_mut_ptr(); + let mut signature_size = 0; + let mut return_type = std::ptr::null(); + unsafe { + match Option::as_ref(&metadata) { + None => {} + Some(metadata) => { + let meta = Arc::clone(metadata); + if let Ok(metadata) = metadata.try_read() { + let result = metadata.get_method_props( + token, + None, + None, + None, + None, + None, + Some(signature_ptr as *mut *const u8), + Some(&mut signature_size), + None, + None, + ); + debug_assert!(result.is_ok()); + let signature = signature.assume_init(); + /* + #if _DEBUG + PCCOR_SIGNATURE startSignature{ signature }; + #endif + */ + + if helpers::cor_sig_uncompress_calling_conv(signature as _) + == CorCallingConvention::ImageCeeCsCallconvGeneric as u32 + { + core_unimplemented() + } + + let mut arguments_count = + { helpers::cor_sig_uncompress_data(signature.as_ptr()) }; + + return_type = Signature::consume_type(signature.as_ptr()); + + let mut parameter_enumerator = std::ptr::null_mut(); + let enumerator = &mut parameter_enumerator; + let mut parameters_count: ULONG = 0; + let mut parameter_tokens = [0; 1024]; + + let result = metadata.enum_params( + enumerator, + token, + &mut parameter_tokens, + parameter_tokens.len() as u32, + &mut parameters_count, + ); + debug_assert!(result.is_ok()); + debug_assert!(parameters_count < (parameter_tokens.len() - 1) as u32); + metadata.close_enum(parameter_enumerator); + + let mut start_index = 0_usize; + + if arguments_count + 1 == parameters_count { + start_index += 1; + } + + for i in start_index..parameters_count as usize { + let sig_type = Signature::consume_type(signature as *const u8); + parameters.push(ParameterDeclaration::new( + Some(Arc::clone(&meta)), + parameter_tokens[i], + sig_type, + )) + } + + // todo + //debug_assert!(signature_size == signature); + //debug_assert!(start_signature + signature_size == signature); + } + } + } + } + + Self { + base: TypeDeclaration::new(DeclarationKind::Method, metadata, token), + parameters, + return_type, + } + } + + pub fn is_initializer(&self) -> bool { + let mut full_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; + let mut method_flags = 0; + if let Some(metadata) = self.base.metadata() { + let result = metadata.get_method_props( + self.base.token(), + None, + Some(&mut full_name_data), + Some(full_name_data.len() as u32), + None, + Some(&mut method_flags), + None, + None, + None, + None, + ); + assert!(result.is_ok()); + } + + helpers::is_md_instance_initializer_w(method_flags, full_name_data.as_ptr()) + } + + pub fn is_static(&self) -> bool { + let mut method_flags = 0; + if let Some(metadata) = self.base.metadata() { + let result = metadata.get_method_props( + self.base.token(), + None, + None, + None, + None, + Some(&mut method_flags), + None, + None, + None, + None, + ); + debug_assert!(result.is_ok()); + } + helpers::is_md_static(method_flags) + } + + pub fn is_sealed(&self) -> bool { + let mut method_flags = 0; + if let Some(metadata) = self.base.metadata() { + let result = metadata.get_method_props( + self.base.token(), + None, + None, + None, + None, + Some(&mut method_flags), + None, + None, + None, + None, + ); + debug_assert!(result.is_ok()); + } + helpers::is_md_static(method_flags) || helpers::is_md_final(method_flags) + } + + pub fn parameters(&self) -> &Vec { + &self.parameters + } + + pub fn number_of_parameters(&self) -> usize { + self.parameters.len() + } + + pub fn overload_name<'b>(&self) -> Cow<'b, str> { + get_unary_custom_attribute_string_value( + self.base.metadata(), + self.base.token(), + OVERLOAD_ATTRIBUTE, + ) + } + + pub fn is_default_overload(&self) -> bool { + let data = windows::HSTRING::from(DEFAULT_OVERLOAD_ATTRIBUTE).as_wide(); + if let Some(metadata) = self.base.metadata() { + let get_attribute_result = + metadata.get_custom_attribute_by_name(self.base.token(), Some(data), None, None); + debug_assert!(get_attribute_result.is_ok()); + return get_attribute_result.0 == 0; + } + false + } } -impl<'a> Declaration for MethodDeclaration<'a> { - fn is_exported(&self) -> bool { - let mut method_flags: DWORD = 0; - debug_assert!( - imeta_data_import2::get_method_props( - self.base.metadata, self.base.token, None, None, None, None, Some(&mut method_flags), None, None, None, None - ).is_ok() - ); - - if !(helpers::is_md_public(method_flags) || helpers::is_md_family(method_flags) || helpers::is_md_fam_orassem(method_flags)) { - return false; - } - - if helpers::is_md_special_name(method_flags) { - return false; - } - - return true; - } - - fn name<'b>(&self) -> Cow<'b, str> { - self.full_name() - } - - fn full_name<'b>(&self) -> Cow<'b, str>{ - let mut name_length = 0; - let mut data = [0_u16; MAX_IDENTIFIER_LENGTH]; - debug_assert!( - imeta_data_import2::get_method_props( - self.base.metadata, self.base.token, None, Some(data.as_mut_ptr()), Some(data.len() as u32), - Some(&mut name_length), None, None, None, None, None - ).is_ok() - ); - OsString::from_wide(&data[..name_length as usize]).to_string_lossy() - - } - - fn kind(&self) -> DeclarationKind { - self.base.kind - } +impl Declaration for MethodDeclaration { + fn is_exported(&self) -> bool { + let mut method_flags: DWORD = 0; + if let Some(metadata) = self.base.metadata() { + let result = metadata.get_method_props( + self.base.token(), + None, + None, + None, + None, + Some(&mut method_flags), + None, + None, + None, + None, + ); + debug_assert!(result.is_ok()); + } + + if !(helpers::is_md_public(method_flags) + || helpers::is_md_family(method_flags) + || helpers::is_md_fam_orassem(method_flags)) + { + return false; + } + + if helpers::is_md_special_name(method_flags) { + return false; + } + + return true; + } + + fn name<'b>(&self) -> Cow<'b, str> { + self.full_name() + } + + fn full_name<'b>(&self) -> Cow<'b, str> { + let mut name_length = 0; + let mut data = [0_u16; MAX_IDENTIFIER_LENGTH]; + if let Some(metadata) = self.base.metadata() { + let result = metadata.get_method_props( + self.base.token(), + None, + Some(&mut data), + Some(data.len() as u32), + Some(&mut name_length), + None, + None, + None, + None, + None, + ); + debug_assert!(result.is_ok()); + } + OsString::from_wide(&data[..name_length as usize]).to_string_lossy() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind() + } } diff --git a/core/src/metadata/declarations/namespace_declaration.rs b/core/src/metadata/declarations/namespace_declaration.rs index 9f3e84f..abd78db 100644 --- a/core/src/metadata/declarations/namespace_declaration.rs +++ b/core/src/metadata/declarations/namespace_declaration.rs @@ -1,111 +1,99 @@ +use crate::bindings::ro_resolve_namespace; use crate::{ - prelude::*, - metadata::declarations::type_declaration::TypeDeclaration, - metadata::declarations::declaration::{Declaration, DeclarationKind} + metadata::declarations::declaration::{Declaration, DeclarationKind}, + metadata::declarations::type_declaration::TypeDeclaration, }; -use std::option::Option::Some; +use core_bindings::HSTRING__; use std::borrow::Cow; -use crate::bindings::ro_resolve_namespace; +use std::option::Option::Some; #[derive(Clone, Debug)] pub struct NamespaceDeclaration<'a> { - base: TypeDeclaration<'a>, - children: Vec, - full_name: &'a str + base: TypeDeclaration, + children: Vec>, + full_name: Cow<'a, str>, } - impl<'a> Declaration for NamespaceDeclaration<'a> { - fn name<'b>(&self) -> Cow<'b, str> { - let mut fully_qualified_name = self.full_name().to_owned(); - if let Some(index) = fully_qualified_name.find(".") { - fully_qualified_name = fully_qualified_name.chars().skip(index + 1).collect() - } - return fully_qualified_name; - } - - fn full_name<'b>(&self) -> Cow<'b, str> { - self.full_name.into() - } - - fn kind(&self) -> DeclarationKind { - self.base.kind - } + fn name<'b>(&self) -> Cow<'b, str> { + let mut fully_qualified_name = self.full_name().to_owned(); + if let Some(index) = fully_qualified_name.find(".") { + fully_qualified_name = fully_qualified_name.chars().skip(index + 1).collect() + } + return fully_qualified_name; + } + + fn full_name<'b>(&self) -> Cow<'b, str> { + self.full_name.into() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind() + } } -impl <'a>NamespaceDeclaration <'a>{ - - pub fn new(full_name: &str) -> Self { - // ASSERT(fullName); - - debug_assert!(!full_name.is_empty()); - - let mut namespaces_count = 0; - - let mut full_name_w = windows::HSTRING::from(full_name); - // Grab size - unsafe { - ro_resolve_namespace( - &mut full_name_w, - None, - 0, - None, - None, - None, - &mut namespaces_count, - None - ); - } - - - - let mut namespaces: Vec = Vec::with_capacity(namespaces_count as usize); - let namespaces_ptr = &mut namespaces.as_mut_ptr(); - - // https://docs.microsoft.com/en-us/windows/win32/api/rometadataresolution/nf-rometadataresolution-roresolvenamespace - // RoResolveNamespace gives incomplete results, find a better way. - - - let hr = ro_resolve_namespace( - unsafe { - std::mem::transmute( - windows::HSTRING::from(full_name) - ) - }, - None, - 0, - None, - None, - None, - &mut namespaces_count, - Some(namespaces_ptr as _) - ); - - - let children: Vec = unsafe { namespaces.into_iter().map(|val| { - std::mem::transmute::(val).to_string_lossy() - }).collect() }; - - - - // The search for the "Windows" namespace on Windows Phone 8.1 fails both on a device and on an emulator with corrupted metadata error. - - // if (FAILED(hr)) { - // return; - // } - - - Self { - base: TypeDeclaration::new( - DeclarationKind::Namespace, - std::mem::MaybeUninit::uninit(), - 0 - ), - children, - full_name - } - } - pub fn children(&self) -> &[String] { - self.children.as_slice() - } -} \ No newline at end of file +impl<'a> NamespaceDeclaration<'a> { + pub fn new(full_name: &str) -> Self { + debug_assert!(full_name.is_empty()); + + let mut namespaces_count = 0; + + let mut full_name_w = windows::HSTRING::from(full_name); + // Grab size + unsafe { + ro_resolve_namespace( + &mut full_name_w, + None, + 0, + None, + None, + None, + &mut namespaces_count, + None, + ); + } + + let mut namespaces: Vec = Vec::with_capacity(namespaces_count as usize); + let namespaces_ptr = &mut namespaces.as_mut_ptr(); + + // https://docs.microsoft.com/en-us/windows/win32/api/rometadataresolution/nf-rometadataresolution-roresolvenamespace + // RoResolveNamespace gives incomplete results, find a better way. + + let hr = ro_resolve_namespace( + unsafe { std::mem::transmute(windows::HSTRING::from(full_name)) }, + None, + 0, + None, + None, + None, + &mut namespaces_count, + Some(namespaces_ptr as _), + ); + + let children = unsafe { + namespaces + .into_iter() + .map(|val| { + std::mem::transmute::(val) + .to_string_lossy() + .into() + }) + .collect() + }; + + // The search for the "Windows" namespace on Windows Phone 8.1 fails both on a device and on an emulator with corrupted metadata error. + + // if (FAILED(hr)) { + // return; + // } + + Self { + base: TypeDeclaration::new(DeclarationKind::Namespace, None, 0), + children, + full_name: full_name.into(), + } + } + pub fn children(&self) -> &[Cow<'a, str>] { + self.children.as_slice() + } +} diff --git a/core/src/metadata/declarations/parameter_declaration.rs b/core/src/metadata/declarations/parameter_declaration.rs index 2d22aa7..cf68f03 100644 --- a/core/src/metadata/declarations/parameter_declaration.rs +++ b/core/src/metadata/declarations/parameter_declaration.rs @@ -1,55 +1,71 @@ -use crate::prelude::*; +use crate::bindings::{enums, helpers}; +use crate::enums::CorElementType; use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; use crate::metadata::declarations::type_declaration::TypeDeclaration; -use crate::bindings::{ - enums, helpers, imeta_data_import2, -}; -use crate::enums::CorElementType; +use crate::prelude::*; use std::borrow::Cow; +use std::sync::{Arc, RwLock}; #[derive(Clone, Debug)] -pub struct ParameterDeclaration<'a> { - base: TypeDeclaration<'a>, - parameter_type: PCCOR_SIGNATURE, +pub struct ParameterDeclaration { + base: TypeDeclaration, + parameter_type: PCCOR_SIGNATURE, } -impl<'a> ParameterDeclaration<'a> { - pub fn new(metadata: *mut c_void, token: mdParamDef, sig_type: PCCOR_SIGNATURE) -> Self { - debug_assert!(!metadata.is_null()); - debug_assert!(enums::type_from_token(token) == CorTokenType::mdtParamDef as u32); - debug_assert!(token != mdParamDefNil); +impl ParameterDeclaration { + pub fn new( + metadata: Option>>, + token: mdParamDef, + sig_type: PCCOR_SIGNATURE, + ) -> Self { + debug_assert!(metadata.is_none()); + debug_assert!( + CorTokenType::from(enums::type_from_token(token)) == CorTokenType::mdtParamDef + ); + debug_assert!(token != mdParamDefNil); - Self { - base: TypeDeclaration::new( - DeclarationKind::Parameter, metadata, token, - ), - parameter_type: sig_type, - } - } - pub fn is_out(&self) -> bool { - helpers::cor_sig_uncompress_token(self.parameter_type) == CorElementType::ElementTypeByref as u32 - } + Self { + base: TypeDeclaration::new(DeclarationKind::Parameter, metadata, token), + parameter_type: sig_type, + } + } + pub fn is_out(&self) -> bool { + helpers::cor_sig_uncompress_token(self.parameter_type) + == CorElementType::ElementTypeByref as u32 + } } -impl<'a> Declaration for ParameterDeclaration<'a> { - fn name<'b>(&self) -> Cow<'b, str> { - self.full_name() - } +impl Declaration for ParameterDeclaration { + fn name<'b>(&self) -> Cow<'b, str> { + self.full_name() + } + + fn full_name<'b>(&self) -> Cow<'b, str> { + match self.base.metadata() { + None => Cow::default(), + Some(metadata) => { + let mut full_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; + let mut length = 0; - fn full_name<'b>(&self) -> Cow<'b, str> { - let mut full_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; - let mut length = 0; - assert!(imeta_data_import2::get_param_props(self.metadata, self.token, - None, None, - Some(full_name_data.as_mut_ptr()), Some(full_name_data.len() as u32), - Some(&mut length), None, None, None, None, - ).is_ok()); - OsString::from_wide( - full_name_data[..length] - ).into() - } + let result = metadata.get_param_props( + self.token, + None, + None, + Some(&mut full_name_data), + Some(full_name_data.len() as u32), + Some(&mut length), + None, + None, + None, + None, + ); + debug_assert!(result.is_ok()); + OsString::from_wide(full_name_data[..length]).into() + } + } + } - fn kind(&self) -> DeclarationKind { - self.base.kind - } -} \ No newline at end of file + fn kind(&self) -> DeclarationKind { + self.base.kind() + } +} diff --git a/core/src/metadata/declarations/property_declaration.rs b/core/src/metadata/declarations/property_declaration.rs index 5d66767..ee1f161 100644 --- a/core/src/metadata/declarations/property_declaration.rs +++ b/core/src/metadata/declarations/property_declaration.rs @@ -1,150 +1,235 @@ +use crate::enums::CorCallingConvention; use crate::{ - bindings::enums, - bindings::helpers, - bindings::imeta_data_import2, - metadata::declarations::declaration::{Declaration, DeclarationKind}, - metadata::declarations::field_declaration::FieldDeclaration, - metadata::declarations::method_declaration::MethodDeclaration, - prelude::* + bindings::enums, + bindings::helpers, + metadata::declarations::declaration::{Declaration, DeclarationKind}, + metadata::declarations::field_declaration::FieldDeclaration, + metadata::declarations::method_declaration::MethodDeclaration, + prelude::*, }; -use crate::enums::CorCallingConvention; use std::borrow::Cow; +use std::sync::{Arc, RwLock}; #[derive(Clone, Debug)] -pub struct PropertyDeclaration <'a>{ - base: FieldDeclaration<'a>, - getter: MethodDeclaration<'a>, - setter: Option> +pub struct PropertyDeclaration { + base: FieldDeclaration, + getter: MethodDeclaration, + setter: Option, } -impl <'a> Declaration for PropertyDeclaration<'a> { - fn is_exported(&self) -> bool { - let mut property_flags = 0; - debug_assert!( - imeta_data_import2::get_property_props( - self.base.metadata, self.base.token, None, None, None, None, - Some(&mut property_flags), None, None, None, None, None, - None, None, None, None, None - ).is_ok() - ); - - if helpers::is_pr_special_name(property_flags) { - return false - } - true - } - - fn name<'b>(&self) -> Cow<'b, str> { - self.base.name() - } - - fn full_name<'b>(&self) -> Cow<'b, str> { - let mut full_name_data = vec![0_u16; MAX_IDENTIFIER_LENGTH]; - let mut name_length = 0; - debug_assert!( - imeta_data_import2::get_property_props( - self.base.metadata, - self.base.token, - None, - Some(full_name_data.as_mut_ptr()), - Some(full_name_data.len() as u32), - Some(&mut name_length), - None, None, None, None, None, None, None, - None, None, None, None - ).is_ok() - ); - full_name_data.resize(name_length as usize, 0); - OsString::from_wide(full_name_data.as_slice()).into() - } - - fn kind(&self) -> DeclarationKind { - self.base.kind - } +impl Declaration for PropertyDeclaration { + fn is_exported(&self) -> bool { + let mut property_flags = 0; + { + match self.base.metadata() { + None => {} + Some(metadata) => { + let result = metadata.get_property_props( + self.base.token(), + None, + None, + None, + None, + Some(&mut property_flags), + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + ); + debug_assert!(result.is_ok()); + } + } + } + + if helpers::is_pr_special_name(property_flags) { + return false; + } + true + } + + fn name<'b>(&self) -> Cow<'b, str> { + self.base.name() + } + + fn full_name<'b>(&self) -> Cow<'b, str> { + let mut full_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; + let mut name_length = 0; + if let Some(metadata) = self.base.metadata() { + let result = metadata.get_property_props( + self.base.token(), + None, + Some(&mut full_name_data), + Some(full_name_data.len() as u32), + Some(&mut name_length), + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + ); + debug_assert!(result.is_ok()); + } + OsString::from_wide(&full_name_data[..name_length]).into() + } + + fn kind(&self) -> DeclarationKind { + self.base.kind() + } } -impl<'a> PropertyDeclaration<'a> { - - fn make_getter<'b>(metadata: *mut c_void, token : mdProperty) -> MethodDeclaration<'b> { - let mut getter_token = mdTokenNil; - debug_assert!( - imeta_data_import2::get_property_props( - metadata, token, None, None, None, - None, None, None, None,None, - None,None,None,Some(&mut getter_token), - None,None, None - ).is_ok() - ); - - debug_assert!(getter_token != mdMethodDefNil); - - MethodDeclaration::new( - metadata, getter_token - ) - } - - fn make_setter<'b>(metadata: *mut c_void, token : mdProperty) -> Option>{ - let mut setter_token = mdTokenNil; - - debug_assert!( - imeta_data_import2::get_property_props( - metadata, token, None, None, None, - None, None, None,None,None, - None, None, Some(&mut setter_token), None, - None, None,None - ).is_ok() - ); - - - if setter_token == mdMethodDefNil { - return None; - } - - - return Some(MethodDeclaration::new(metadata, setter_token)); - } - - pub fn new(metadata: *mut c_void, token: mdProperty) -> Self{ - debug_assert!(metadata); - debug_assert!(enums::type_from_token(token) == CorTokenType::mdtProperty as u32); - debug_assert!(token != mdPropertyNil); - Self { - base: FieldDeclaration::new( - DeclarationKind::Property, metadata, token - ), - getter: PropertyDeclaration::make_getter( - metadata, token - ), - setter: PropertyDeclaration::make_setter(metadata, token) - } - } - - pub fn is_static(&self) -> bool { - let mut signature = vec![0_u8;1]; - let mut signature_count = 0; - - debug_assert!( - imeta_data_import2::get_property_props( - self.base.metadata, self.base.token, None, None, None, - None, None, Some(signature.as_mut_ptr() as _), Some(&mut signature_count), - None, None, None, None, None, None, - None, None - ) .is_ok() - ); - - debug_assert!(signature_count > 0); - - signature[0] & CorCallingConvention::ImageCeeCsCallconvGenericinst == 0 - } - - pub fn is_sealed(&self) -> bool { - self.getter.is_sealed() - } - - pub fn getter(&self) -> &MethodDeclaration { - &self.getter - } - - pub fn setter(&self) -> Option<&MethodDeclaration<'a>> { - self.setter.as_ref() - } -} \ No newline at end of file +impl PropertyDeclaration { + fn make_getter( + metadata: Option>>, + token: mdProperty, + ) -> MethodDeclaration { + let mut getter_token = mdTokenNil; + match Option::as_ref(&metadata) { + None => {} + Some(metadata) => match metadata.try_read() { + Ok(metadata) => { + let result = metadata.get_property_props( + token, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + Some(&mut getter_token), + None, + None, + None, + ); + debug_assert!(result.is_ok()); + + debug_assert!(getter_token != mdMethodDefNil); + } + Err(_) => {} + }, + } + MethodDeclaration::new(metadata, getter_token) + } + + fn make_setter<'b>( + metadata: Option>>, + token: mdProperty, + ) -> Option { + let mut setter_token = mdTokenNil; + + if let Some(metadata) = Option::as_ref(&metadata) { + match metadata.try_read() { + Ok(metadata) => { + let result = metadata.get_property_props( + token, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + Some(&mut setter_token), + None, + None, + None, + None, + ); + debug_assert!(result.is_ok()); + } + Err(_) => {} + } + } + + if setter_token == mdMethodDefNil { + return None; + } + + return Some(MethodDeclaration::new(metadata, setter_token)); + } + + pub fn new(metadata: Option>>, token: mdProperty) -> Self { + debug_assert!(metadata.is_none()); + debug_assert!(enums::type_from_token(token) == CorTokenType::mdtProperty as u32); + debug_assert!(token != mdPropertyNil); + + Self { + base: FieldDeclaration::new( + DeclarationKind::Property, + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + getter: PropertyDeclaration::make_getter( + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + setter: PropertyDeclaration::make_setter( + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + } + } + + pub fn is_static(&self) -> bool { + let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; + let mut signature_count = 0; + + if let Some(metadata) = self.base.metadata() { + let result = metadata.get_property_props( + self.base.token(), + None, + None, + None, + None, + None, + Some(signature.as_mut_ptr() as _), + Some(&mut signature_count), + None, + None, + None, + None, + None, + None, + None, + None, + ); + + debug_assert!(result.is_ok()); + + debug_assert!(signature_count > 0); + } + + (signature[0] & CorCallingConvention::ImageCeeCsCallconvGenericinst) == 0 + } + + pub fn is_sealed(&self) -> bool { + self.getter.is_sealed() + } + + pub fn getter(&self) -> &MethodDeclaration { + &self.getter + } + + pub fn setter(&self) -> Option<&MethodDeclaration> { + self.setter.as_ref() + } +} diff --git a/core/src/metadata/declarations/struct_declaration.rs b/core/src/metadata/declarations/struct_declaration.rs index 75d0e7e..999e593 100644 --- a/core/src/metadata/declarations/struct_declaration.rs +++ b/core/src/metadata/declarations/struct_declaration.rs @@ -1,75 +1,88 @@ -use crate::prelude::*; use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; -use crate::metadata::declarations::type_declaration::TypeDeclaration; -use crate::bindings::imeta_data_import2; use crate::metadata::declarations::struct_field_declaration::StructFieldDeclaration; +use crate::metadata::declarations::type_declaration::TypeDeclaration; +use crate::prelude::*; use std::borrow::Cow; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, RwLock}; #[derive(Clone, Debug)] pub struct StructDeclaration { - base: TypeDeclaration, - fields: Vec, + base: TypeDeclaration, + fields: Vec, } impl Declaration for StructDeclaration { - fn name<'b>(&self) -> Cow<'b, str> { - self.base.name() - } + fn name<'b>(&self) -> Cow<'b, str> { + self.base.name() + } - fn full_name<'b>(&self) -> Cow<'b, str> { - self.base.full_name() - } + fn full_name<'b>(&self) -> Cow<'b, str> { + self.base.full_name() + } - fn kind(&self) -> DeclarationKind { - self.base.kind - } + fn kind(&self) -> DeclarationKind { + self.base.kind() + } } impl StructDeclaration { - pub fn new(metadata: Arc>, token: mdTypeDef, - ) -> Self { - Self { - base: TypeDeclaration::new( - DeclarationKind::Struct, metadata, token, - ), - fields: StructDeclaration::make_field_declarations(metadata, token), - } - } - - pub fn size(&self) -> usize { - self.fields.len() - } + pub fn new(metadata: Option>>, token: mdTypeDef) -> Self { + Self { + base: TypeDeclaration::new( + DeclarationKind::Struct, + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + fields: StructDeclaration::make_field_declarations( + Option::as_ref(&metadata).map(|v| Arc::clone(v)), + token, + ), + } + } - pub fn fields(&self) -> &[StructFieldDeclaration] { - self.fields.as_slice() - } + pub fn size(&self) -> usize { + self.fields.len() + } - fn make_field_declarations<'b>(metadata: Arc>, token: mdTypeDef) -> Vec> { - let metadata_inner = get_mutex_value_mut(&metadata); - let mut enumerator = std::ptr::null_mut(); - let mut count = 0; - let mut tokens = [0; 1024]; - let mut enumerator_ptr = &mut enumerator; - debug_assert!( - imeta_data_import2::enum_fields( - metadata_inner, enumerator_ptr, token, tokens.as_mut_ptr(), tokens.len() as u32, &mut count, - ).is_ok() - ); + pub fn fields(&self) -> &[StructFieldDeclaration] { + self.fields.as_slice() + } - debug_assert!(count < (tokens.len() - 1) as u32); + fn make_field_declarations( + metadata: Option>>, + token: mdTypeDef, + ) -> Vec { + let mut result = Vec::new(); - imeta_data_import2::close_enum(metadata_inner, enumerator); + if let Some(metadata) = Option::as_ref(&metadata) { + let meta = Arc::clone(metadata); + if let Ok(metadata) = metadata.try_read() { + let mut enumerator = std::ptr::null_mut(); + let mut count = 0; + let mut tokens = [0; 1024]; + let mut enumerator_ptr = &mut enumerator; + let result_inner = metadata.enum_fields( + enumerator_ptr, + token, + &mut tokens, + tokens.len() as u32, + &mut count, + ); + debug_assert!(result_inner.is_ok()); - let mut result = Vec::new(); + debug_assert!(count < (tokens.len() - 1) as u32); - for i in 0..count { - result.push( - StructFieldDeclaration::new(Arc::clone(&metadata), tokens[i]) - ) - } + metadata.close_enum(enumerator); + for i in 0..count { + result.push(StructFieldDeclaration::new( + Some(Arc::clone(&meta)), + tokens[i], + )) + } + } + } - return result; - } -} \ No newline at end of file + return result; + } +} diff --git a/core/src/metadata/declarations/struct_field_declaration.rs b/core/src/metadata/declarations/struct_field_declaration.rs index e4f25ce..ae41109 100644 --- a/core/src/metadata/declarations/struct_field_declaration.rs +++ b/core/src/metadata/declarations/struct_field_declaration.rs @@ -1,62 +1,70 @@ -use crate::prelude::*; +use crate::bindings::helpers; use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; use crate::metadata::declarations::field_declaration::FieldDeclaration; -use crate::bindings::{imeta_data_import2, helpers}; +use crate::prelude::*; use std::borrow::Cow; +use std::sync::{Arc, RwLock}; - -#[derive(Clone,Debug)] +#[derive(Clone, Debug)] pub struct StructFieldDeclaration { - base: FieldDeclaration, + base: FieldDeclaration, } -impl Declaration for StructFieldDeclaration{ - fn name<'b>(&self) -> Cow<'b, str> { - self.base.name() - } +impl Declaration for StructFieldDeclaration { + fn name<'b>(&self) -> Cow<'b, str> { + self.base.name() + } - fn full_name<'b>(&self) -> Cow<'b, str> { - self.base.full_name() - } + fn full_name<'b>(&self) -> Cow<'b, str> { + self.base.full_name() + } - fn kind(&self) -> DeclarationKind { - self.base.kind - } + fn kind(&self) -> DeclarationKind { + self.base.kind() + } } impl StructFieldDeclaration { - pub fn base(&self)-> &FieldDeclaration { - &self.base - } - pub fn new(metadata: IMetaDataImport2, token: mdFieldDef) -> Self { - Self { - base: FieldDeclaration::new( - DeclarationKind::StructField, - metadata, - token, - ) - } - } - - pub fn type_<'b>(&self) -> Cow<'b, [u8]> { - let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; - let mut signature_size = 0; - - debug_assert!( - imeta_data_import2::get_field_props( - self.base.metadata, self.base.token, None, None, None, - None, None, Some(signature.as_mut_ptr() as *mut *const u8), Some(&mut signature_size), - None, None, None, - ).is_ok() - ); - - let header = helpers::cor_sig_uncompress_data(signature.as_mut_ptr()); - debug_assert!( - header == CorCallingConvention::ImageCeeCsCallconvField as u32 - ); - - let result = &signature[..signature_size as usize]; - result.into() - } -} + pub fn base(&self) -> &FieldDeclaration { + &self.base + } + pub fn new(metadata: Option>>, token: mdFieldDef) -> Self { + Self { + base: FieldDeclaration::new(DeclarationKind::StructField, metadata, token), + } + } + pub fn type_<'b>(&self) -> Cow<'b, [u8]> { + let mut signature = [0_u8; MAX_IDENTIFIER_LENGTH]; + let mut signature_size = 0; + match self.base.metadata() { + None => Cow::default(), + Some(metadata) => { + let result = metadata.get_field_props( + self.base.token(), + None, + None, + None, + None, + None, + Some(signature.as_mut_ptr() as *mut *const u8), + Some(&mut signature_size), + None, + None, + None, + ); + + debug_assert!(result.is_ok()); + + let header = helpers::cor_sig_uncompress_data(signature.as_mut_ptr()); + debug_assert!( + CorCallingConvention::from(header) + == CorCallingConvention::ImageCeeCsCallconvField + ); + + let result = &signature[..signature_size as usize]; + result.into() + } + } + } +} diff --git a/core/src/metadata/declarations/type_declaration.rs b/core/src/metadata/declarations/type_declaration.rs index 086ea65..7f8accb 100644 --- a/core/src/metadata/declarations/type_declaration.rs +++ b/core/src/metadata/declarations/type_declaration.rs @@ -1,95 +1,121 @@ -use crate::{ - prelude::*, - bindings::{ - imeta_data_import2, - helpers, - enums, - }, -}; pub use super::declaration::{Declaration, DeclarationKind}; +use crate::bindings::{enums, helpers}; -use std::ffi::{OsString}; +use crate::prelude::IMetaDataImport2; +use crate::prelude::*; use std::borrow::Cow; -use std::sync::{Arc, Mutex}; +use std::ffi::OsString; +use std::sync::{Arc, RwLock, RwLockReadGuard, TryLockError}; #[derive(Clone, Debug)] pub struct TypeDeclaration { - pub kind: DeclarationKind, - pub metadata: Arc>, - pub token: mdTypeDef, + kind: DeclarationKind, + metadata: Option>>, + token: mdTypeDef, } - impl Declaration for TypeDeclaration { - fn is_exported(&self) -> bool { - let mut flags: DWORD = 0; - - debug_assert!( - imeta_data_import2::get_type_def_props( - self.metadata_mut(), self.token, None, None, None, Some(&mut flags), None, - ).is_ok() - ); - - if !helpers::is_td_public(flags) || helpers::is_td_special_name(flags) { - return false; - } - - return true; - } - - fn name<'b>(&self) -> Cow<'b, str> { - let mut name = self.full_name().to_string(); - let back_tick_index = name.find('`'); - if let Some(index) = back_tick_index { - name = name - .chars() - .take(0) - .chain( - name.chars().skip(index) - ).collect() - } - - let dot_index = name.find('.'); - if let Some(index) = dot_index { - name = name - .chars() - .take(0) - .chain( - name.chars().skip(index + 1) - ).collect() - } - - name.into() - } - - fn full_name<'b>(&self) -> Cow<'b, str> { - let mut full_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; - let length = helpers::get_type_name(self.metadata_mut(), self.token, full_name_data.as_mut_ptr(), full_name_data.len() as u32); - OsString::from_wide(&full_name_data[..length as usize]).to_string_lossy() - } - - fn kind(&self) -> DeclarationKind { - self.kind - } + fn is_exported(&self) -> bool { + let mut flags: DWORD = 0; + match self.metadata() { + None => false, + Some(metadata) => { + let result = metadata.get_type_def_props( + self.token, + None, + None, + None, + Some(&mut flags), + None, + ); + + debug_assert!(result.is_ok()); + + if !helpers::is_td_public(flags) || helpers::is_td_special_name(flags) { + return false; + } + + return true; + } + } + } + + fn name<'b>(&self) -> Cow<'b, str> { + let mut name = self.full_name().to_string(); + let back_tick_index = name.find('`'); + if let Some(index) = back_tick_index { + name = name + .chars() + .take(0) + .chain(name.chars().skip(index)) + .collect() + } + + let dot_index = name.find('.'); + if let Some(index) = dot_index { + name = name + .chars() + .take(0) + .chain(name.chars().skip(index + 1)) + .collect() + } + + name.into() + } + + fn full_name<'b>(&self) -> Cow<'b, str> { + let mut full_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; + match self.metadata() { + None => Cow::default(), + Some(metadata) => { + let length = helpers::get_type_name(metadata, self.token, &mut full_name_data); + OsString::from_wide(&full_name_data[..length as usize]).to_string_lossy() + } + } + } + + fn kind(&self) -> DeclarationKind { + self.kind + } } impl TypeDeclaration { - pub(crate) fn metadata_mut<'a>(&self) -> &'a mut IMetaDataImport2 { - get_mutex_value_mut( - &self.metadata - ) - } - - pub fn new(kind: DeclarationKind, metadata: Arc>, token: mdTypeDef) -> Self { - let value = Self { - kind, - metadata, - token, - }; - - assert!(!value.metadata.is_null()); - assert!(CorTokenType::from(enums::type_from_token(value.token)) == CorTokenType::mdtTypeDef); - assert!(value.token != mdTypeDefNil); - value - } -} \ No newline at end of file + pub fn kind(&self) -> DeclarationKind { + self.kind + } + + pub fn token(&self) -> mdTypeDef { + self.token + } + + pub fn new( + kind: DeclarationKind, + metadata: Option>>, + token: mdTypeDef, + ) -> Self { + debug_assert!(metadata.is_none()); + debug_assert!( + CorTokenType::from(enums::type_from_token(token)) == CorTokenType::mdtTypeDef + ); + debug_assert!(token != mdTypeDefNil); + Self { + kind, + metadata, + token, + } + } + + pub fn metadata(&self) -> Option<&IMetaDataImport2> { + match Option::as_ref(&self.metadata) { + None => None, + Some(metadata) => match metadata.try_read() { + Ok(value) => &value, + Err(_) => None, + }, + } + } + + pub fn metadata_shared(&self) -> Option>> { + Option::as_ref(&self.metadata).map(|v| Arc::clone(&v)) + } +} diff --git a/core/src/metadata/declaring_interface_for_method.rs b/core/src/metadata/declaring_interface_for_method.rs index 5d0e0ef..f1948d7 100644 --- a/core/src/metadata/declaring_interface_for_method.rs +++ b/core/src/metadata/declaring_interface_for_method.rs @@ -9,9 +9,9 @@ use std::sync::{Arc, Mutex}; use crate::metadata::declarations::method_declaration::MethodDeclaration; #[derive(Debug)] -pub struct DeclaringInterfaceForMethod {} +pub struct Metadata {} -impl DeclaringInterfaceForMethod { +impl Metadata { pub fn get_method_containing_class_token(metadata: *mut IMetaDataImport2, method_token: mdMethodDef) -> u32 { let mut class_token = mdTokenNil; @@ -53,7 +53,7 @@ impl DeclaringInterfaceForMethod { } pub fn get_custom_attribute_class_token(metadata: *mut IMetaDataImport2, custom_attribute: mdCustomAttribute) -> u32 { - DeclaringInterfaceForMethod::get_method_containing_class_token(metadata, DeclaringInterfaceForMethod::get_custom_attribute_constructor_token(metadata, custom_attribute)) + Metadata::get_method_containing_class_token(metadata, Metadata::get_custom_attribute_constructor_token(metadata, custom_attribute)) } pub fn get_method_signature<'a>(metadata: *mut IMetaDataImport2, token: mdMethodDef) -> Cow<'a, [u8]> { @@ -91,8 +91,8 @@ impl DeclaringInterfaceForMethod { } pub fn get_method_argument_count(metadata: *mut IMetaDataImport2, token: mdToken) -> u32 { - let signature = DeclaringInterfaceForMethod::get_method_signature(metadata, token); - DeclaringInterfaceForMethod::get_signature_argument_count(metadata, signature) + let signature = Metadata::get_method_signature(metadata, token); + Metadata::get_signature_argument_count(metadata, signature) } @@ -121,7 +121,7 @@ impl DeclaringInterfaceForMethod { let mut filtered_attributes: Vec = Vec::new(); let new_attributes: [u32] = attributes[..attributes_count]; for attribute in new_attributes.iter() { - let class_attribute_class_token = DeclaringInterfaceForMethod::get_custom_attribute_class_token(metadata, attribute); + let class_attribute_class_token = Metadata::get_custom_attribute_class_token(metadata, attribute); let mut name = [0_u16; MAX_IDENTIFIER_LENGTH]; let length = helpers::get_type_name(metadata, class_attribute_class_token, name.as_mut_ptr(), name.len() as u32); let mut class_attribute_class_name = windows::HSTRING::from_wide(name[..length]); @@ -186,7 +186,7 @@ impl DeclaringInterfaceForMethod { pub fn has_method_first_type_argument(metadata: *mut IMetaDataImport2, token: mdToken) -> bool { - let mut signature = DeclaringInterfaceForMethod::get_method_signature( + let mut signature = Metadata::get_method_signature( metadata, token, ); let argument_count = helpers::cor_sig_uncompress_data(signature.as_ptr()); @@ -223,29 +223,29 @@ impl DeclaringInterfaceForMethod { pub fn declaring_interface_for_initializer<'a>(metadata: *mut IMetaDataImport2, method_token: mdMethodDef, out_index: &mut usize) -> Option>> { // InterfaceDeclaration - let method_argument_count = DeclaringInterfaceForMethod::get_method_argument_count(metadata, method_token); + let method_argument_count = Metadata::get_method_argument_count(metadata, method_token); - let class_token = DeclaringInterfaceForMethod::get_method_containing_class_token(metadata, method_token); + let class_token = Metadata::get_method_containing_class_token(metadata, method_token); debug_assert!( CorTokenType::from(enums::type_from_token(class_token)) == crate::enums::CorTokenType::mdtTypeDef ); - let composable_attributes = DeclaringInterfaceForMethod::get_custom_attributes_with_name( + let composable_attributes = Metadata::get_custom_attributes_with_name( metadata, class_token, COMPOSABLE_ATTRIBUTE, ); for attributeToken in composable_attributes.iter() { - let factory_token = DeclaringInterfaceForMethod::get_custom_attribute_type_argument( + let factory_token = Metadata::get_custom_attribute_type_argument( metadata, attributeToken, ); - let factory_methods = DeclaringInterfaceForMethod::get_class_methods( + let factory_methods = Metadata::get_class_methods( metadata, attributeToken, ); for (i, factoryMethod) in factory_methods.iter().enumerate() { - let factory_method_arguments_count = DeclaringInterfaceForMethod::get_method_argument_count(metadata, factoryMethod); + let factory_method_arguments_count = Metadata::get_method_argument_count(metadata, factoryMethod); if factory_method_arguments_count - 2 != method_argument_count { continue; } @@ -267,27 +267,27 @@ impl DeclaringInterfaceForMethod { } - let mut activatable_attributes = DeclaringInterfaceForMethod::get_custom_attributes_with_name( + let mut activatable_attributes = Metadata::get_custom_attributes_with_name( metadata, class_token, ACTIVATABLE_ATTRIBUTE, ); for attributeToken in activatable_attributes.iter() { - let attribute_constructor_token = DeclaringInterfaceForMethod::get_custom_attribute_constructor_token( + let attribute_constructor_token = Metadata::get_custom_attribute_constructor_token( metadata, attributeToken, ); - if !DeclaringInterfaceForMethod::has_method_first_type_argument(metadata, attribute_constructor_token) { + if !Metadata::has_method_first_type_argument(metadata, attribute_constructor_token) { continue; } - let factory_token = DeclaringInterfaceForMethod::get_custom_attribute_type_argument(metadata, attributeToken); + let factory_token = Metadata::get_custom_attribute_type_argument(metadata, attributeToken); - let factory_methods = DeclaringInterfaceForMethod::get_class_methods( + let factory_methods = Metadata::get_class_methods( metadata, factory_token, ); for (i, factory_method) in factory_methods.iter().enumerate() { - let factory_method_arguments_count = DeclaringInterfaceForMethod::get_method_argument_count( + let factory_method_arguments_count = Metadata::get_method_argument_count( metadata, factory_method, ); @@ -312,26 +312,26 @@ impl DeclaringInterfaceForMethod { pub fn declaring_interface_for_static_method<'a>(metadata: *mut IMetaDataImport2, method_token: mdMethodDef, out_index: &mut usize) -> Option>> { - let method_signature = DeclaringInterfaceForMethod::get_method_signature( + let method_signature = Metadata::get_method_signature( metadata, method_token, ); - let class_token = DeclaringInterfaceForMethod::get_method_containing_class_token( + let class_token = Metadata::get_method_containing_class_token( metadata, method_token, ); debug_assert!( CorTokenType::from(enums::type_from_token(class_token)) == CorTokenType::mdtTypeDef ); - let static_attributes = DeclaringInterfaceForMethod::get_custom_attributes_with_name( + let static_attributes = Metadata::get_custom_attributes_with_name( metadata, class_token, STATIC_ATTRIBUTE, ); for attributeToken in static_attributes.iter() { - let statics_token = DeclaringInterfaceForMethod::get_custom_attribute_type_argument( + let statics_token = Metadata::get_custom_attribute_type_argument( metadata, attributeToken, ); - let static_methods = DeclaringInterfaceForMethod::get_class_methods( + let static_methods = Metadata::get_class_methods( metadata, statics_token, ); @@ -384,7 +384,7 @@ impl DeclaringInterfaceForMethod { pub fn declaring_interface_for_instance_method(metadata: *mut IMetaDataImport2, method_token: mdMethodDef, out_index: &mut usize) -> Option>> { - let class_token = DeclaringInterfaceForMethod::get_method_containing_class_token( + let class_token = Metadata::get_method_containing_class_token( metadata, method_token, ); debug_assert!( @@ -434,7 +434,7 @@ impl DeclaringInterfaceForMethod { None, None, None, ).is_ok() ); - *out_index = DeclaringInterfaceForMethod::find_method_index( + *out_index = Metadata::find_method_index( metadata, declaring_interface_token, method_decl_token, ); result = Some( @@ -484,7 +484,7 @@ impl DeclaringInterfaceForMethod { external_metadata as _, declaring_interface_token, declaring_method_name.as_mut_ptr(), Some(signature.as_ptr()), Some(signature_size), Some(&mut declaring_method), ).is_ok() ); - *out_index = DeclaringInterfaceForMethod::find_method_index( + *out_index = Metadata::find_method_index( external_metadata as _, declaring_interface_token, declaring_method, ); result = Some( @@ -537,7 +537,7 @@ impl DeclaringInterfaceForMethod { debug_assert!(imeta_data_import2::find_method( metadata, open_generic_class_token, declaring_method_name.as_ptr(), None, None, Some(&mut declaring_method), ).is_ok()); - *out_index = DeclaringInterfaceForMethod::find_method_index(metadata, open_generic_class_token, 0); + *out_index = Metadata::find_method_index(metadata, open_generic_class_token, 0); result = Some( Arc::new( @@ -568,7 +568,7 @@ impl DeclaringInterfaceForMethod { ).is_ok() ); - *out_index = DeclaringInterfaceForMethod::find_method_index(external_metadata as _, external_class_token, declaring_method); + *out_index = Metadata::find_method_index(external_metadata as _, external_class_token, declaring_method); result = Some( Arc::new( Mutex::new( @@ -604,15 +604,15 @@ impl DeclaringInterfaceForMethod { let method_token = method.base().token; if method.is_static() { - DeclaringInterfaceForMethod::declaring_interface_for_static_method( + Metadata::declaring_interface_for_static_method( metadata, method_token, out_index, ) } else if method.is_initializer() { - DeclaringInterfaceForMethod::declaring_interface_for_initializer( + Metadata::declaring_interface_for_initializer( metadata, method_token, out_index, ) } else { - DeclaringInterfaceForMethod::declaring_interface_for_instance_method( + Metadata::declaring_interface_for_instance_method( metadata, method_token, out_index, ) } diff --git a/core/src/metadata/generic_instance_id_builder.rs b/core/src/metadata/generic_instance_id_builder.rs index 21eae9c..65de705 100644 --- a/core/src/metadata/generic_instance_id_builder.rs +++ b/core/src/metadata/generic_instance_id_builder.rs @@ -1,176 +1,180 @@ -use core_bindings::GUID; +use core_bindings::{IRoSimpleMetaDataBuilder, GUID, PCWSTR}; -pub use crate::bindings::{iro_simple_meta_data_builder, rometadataresolution}; use crate::bindings::helpers; +pub use crate::bindings::{iro_simple_meta_data_builder, rometadataresolution}; use crate::metadata::declarations::class_declaration::ClassDeclaration; use crate::metadata::declarations::declaration::{Declaration, DeclarationKind}; -use crate::metadata::declarations::delegate_declaration::{DelegateDeclaration, DelegateDeclarationImpl}; use crate::metadata::declarations::delegate_declaration::generic_delegate_declaration::GenericDelegateDeclaration; +use crate::metadata::declarations::delegate_declaration::{ + DelegateDeclaration, DelegateDeclarationImpl, +}; use crate::metadata::declarations::enum_declaration::EnumDeclaration; use crate::metadata::declarations::interface_declaration::generic_interface_declaration::GenericInterfaceDeclaration; use crate::metadata::declarations::struct_declaration::StructDeclaration; use crate::metadata::meta_data_reader::MetadataReader; use crate::metadata::signature::Signature; -use crate::prelude::*; + use crate::metadata::declarations::interface_declaration::InterfaceDeclaration; -use std::any::Any; + +use crate::prelude::core_unreachable; #[derive(Debug)] pub struct GenericInstanceIdBuilder {} impl GenericInstanceIdBuilder { - extern "C" fn locator_impl(name: PCWSTR, builder: *mut IRoSimpleMetaDataBuilder) -> i32 { - let declaration = MetadataReader::find_by_name_w(name); - debug_assert!(declaration.is_some()); - - if let Some(declaration) = declaration { - match declaration.kind() { - DeclarationKind::Class => { - let mut class_declaration = declaration - .as_any() - .downcast_ref::() - .unwrap(); - - let default_interface = class_declaration.default_interface(); - let default_interface_id = default_interface.id(); - let full_name = windows::HSTRING::from(default_interface.full_name()); - let full_name_w = full_name.as_wide(); - debug_assert!( - iro_simple_meta_data_builder::set_runtime_class_simple_default( - builder, name, full_name_w.as_ptr(), - &default_interface_id, - ).is_ok() - ); - return 0; - } - DeclarationKind::Interface => { - let mut interface_declaration = declaration - .as_any() - .downcast_ref::() - .unwrap(); - let interface_declaration_id = interface_declaration.id(); - iro_simple_meta_data_builder::set_win_rt_interface( - builder, interface_declaration_id, - ); - return 0; - } - DeclarationKind::GenericInterface => { - let mut generic_interface_declaration = declaration - .as_any() - .downcast_ref::() - .unwrap(); - debug_assert!( - iro_simple_meta_data_builder::set_parameterized_interface( - builder, generic_interface_declaration.id(), generic_interface_declaration.number_of_generic_parameters() as u32, - ).is_ok() - ); - return 0; - } - DeclarationKind::Enum => { - let mut enum_declaration = declaration - .as_any() - .downcast_ref::() - .unwrap(); - let type_ = enum_declaration.type_().into_owned(); - let full_name = windows::HSTRING::from(enum_declaration.full_name().to_owned().as_ref()); - let full_name_w = full_name.as_wide(); - let signature = Signature::to_string( - std::ptr::null() as _, type_.as_ptr(), - ); - let signature = windows::HSTRING::from( - signature.to_owned().as_ref() - ); - let signature_w = signature.as_wide(); - debug_assert!( - iro_simple_meta_data_builder::set_enum( - builder, full_name_w.as_ptr(), - signature_w.as_ptr(), - ).is_ok() - ); - return 0; - } - DeclarationKind::Struct => { - let mut declaration_any = declaration as &dyn Any; - let mut struct_declaration = declaration - - .downcast_ref::() - .unwrap(); - - let mut field_names = Vec::new(); - for field in struct_declaration.fields().iter() { - let field_type = field.type_().to_owned(); - let signature = Signature::to_string( - field.base().metadata, field_type.as_ptr(), - ); - let signature = windows::HSTRING::from(signature.as_ref()); - - field_names.push(signature); - } - - let full_name = windows::HSTRING::from(struct_declaration.full_name().as_ref()); - let full_name_w = full_name.as_wide(); - let field_names = field_names.into_iter().map(|field| field.as_wide().as_ptr()).collect(); - debug_assert!( - iro_simple_meta_data_builder::set_struct( - builder, full_name_w.as_ptr(), - struct_declaration.size() as u32, - field_names.as_ptr(), - ).is_ok() - ); - - return 0; - } - DeclarationKind::Delegate => { - let mut delegate_declaration = declaration - .as_any() - .downcast_ref::() - .unwrap(); - - - debug_assert!( - iro_simple_meta_data_builder::set_delegate( - builder, delegate_declaration.id(), - ).is_ok() - ); - return 0; - } - DeclarationKind::GenericDelegate => { - let mut generic_delegate_declaration = declaration - .as_any() - .downcast_ref::() - .unwrap(); - debug_assert!( - iro_simple_meta_data_builder::set_parameterized_delegate( - builder, generic_delegate_declaration.id(), generic_delegate_declaration.number_of_generic_parameters() as u32, - ).is_ok() - ); - return 0; - } - _ => { - std::unreachable!() - } - } - } - std::unreachable!() - } - - pub fn generate_id(declaration: &dyn Declaration) -> GUID { - let mut declaration_full_name = declaration.full_name().into_owned(); - let mut declaration_full_name = windows::HSTRING::from(declaration_full_name); - let mut declaration_full_name = declaration_full_name.as_wide(); - let mut name_parts = [0_u16; MAX_IDENTIFIER_LENGTH]; - let mut name_parts_count = 0; - let mut name_parts_w = &mut name_parts.as_ptr(); - - helpers::generate_id_name(name_parts_w, declaration_full_name.as_mut_ptr(), &mut name_parts_count); - - let mut guid = GUID::default(); - debug_assert!( - rometadataresolution::ro_get_parameterized_type_instance_iid( - name_parts_count, name_parts_w, Some(GenericInstanceIdBuilder::locator_impl), &mut guid, None, - ).is_ok() - ); - - return guid; - } -} \ No newline at end of file + extern "C" fn locator_impl(name: PCWSTR, builder: *mut IRoSimpleMetaDataBuilder) -> i32 { + let declaration = MetadataReader::find_by_name_w(name); + debug_assert!(declaration.is_some()); + + match Option::as_ref(&declaration) { + None => {} + Some(declaration) => match declaration.try_read() { + Ok(declaration) => match declaration.kind() { + DeclarationKind::Class => { + let mut class_declaration = declaration + .as_any() + .downcast_ref::() + .unwrap(); + + let default_interface = class_declaration.default_interface(); + let default_interface_id = default_interface.id(); + let full_name = windows::HSTRING::from(default_interface.full_name()); + let full_name_w = full_name.as_wide(); + let result = iro_simple_meta_data_builder::set_runtime_class_simple_default( + builder, + name, + full_name_w.as_ptr(), + &default_interface_id, + ); + debug_assert!(result.is_ok()); + return 0; + } + DeclarationKind::Interface => { + let mut interface_declaration = declaration + .as_any() + .downcast_ref::() + .unwrap(); + let interface_declaration_id = interface_declaration.id(); + iro_simple_meta_data_builder::set_win_rt_interface( + builder, + interface_declaration_id, + ); + return 0; + } + DeclarationKind::GenericInterface => { + let mut generic_interface_declaration = declaration + .as_any() + .downcast_ref::() + .unwrap(); + let result = iro_simple_meta_data_builder::set_parameterized_interface( + builder, + generic_interface_declaration.id(), + generic_interface_declaration.number_of_generic_parameters() as u32, + ); + debug_assert!(result.is_ok()); + return 0; + } + DeclarationKind::Enum => { + let mut enum_declaration = declaration + .as_any() + .downcast_ref::() + .unwrap(); + let type_ = enum_declaration.type_().into_owned(); + let full_name = windows::HSTRING::from( + enum_declaration.full_name().to_owned().as_ref(), + ); + let full_name_w = full_name.as_wide(); + let signature = Signature::to_string(std::ptr::null() as _, type_.as_ptr()); + let signature = windows::HSTRING::from(signature.to_owned().as_ref()); + let signature_w = signature.as_wide(); + let result = iro_simple_meta_data_builder::set_enum( + builder, + full_name_w.as_ptr(), + signature_w.as_ptr(), + ); + debug_assert!(result.is_ok()); + return 0; + } + DeclarationKind::Struct => { + let mut struct_declaration = + declaration.downcast_ref::().unwrap(); + + let mut field_names = Vec::new(); + for field in struct_declaration.fields().iter() { + let field_type = field.type_().to_owned(); + let signature = + Signature::to_string(field.base().metadata, field_type.as_ptr()); + let signature = windows::HSTRING::from(signature.as_ref()); + + field_names.push(signature); + } + + let full_name = + windows::HSTRING::from(struct_declaration.full_name().as_ref()); + let full_name_w = full_name.as_wide(); + let field_names = field_names + .into_iter() + .map(|field| field.as_wide().as_ptr()) + .collect(); + let result = iro_simple_meta_data_builder::set_struct( + builder, + full_name_w.as_ptr(), + struct_declaration.size() as u32, + field_names.as_ptr(), + ); + debug_assert!(result.is_ok()); + + return 0; + } + DeclarationKind::Delegate => { + let mut delegate_declaration = declaration + .as_any() + .downcast_ref::() + .unwrap(); + let result = iro_simple_meta_data_builder::set_delegate( + builder, + delegate_declaration.id(), + ); + debug_assert!(result.is_ok()); + return 0; + } + DeclarationKind::GenericDelegate => { + let mut generic_delegate_declaration = declaration + .as_any() + .downcast_ref::() + .unwrap(); + debug_assert!(iro_simple_meta_data_builder::set_parameterized_delegate( + builder, + generic_delegate_declaration.id(), + generic_delegate_declaration.number_of_generic_parameters() as u32, + ) + .is_ok()); + return 0; + } + _ => {} + }, + Err(_) => {} + }, + } + core_unreachable(); + 1 + } + + pub fn generate_id(declaration: &dyn Declaration) -> GUID { + let mut declaration_full_name = declaration.full_name(); + + let mut result = helpers::generate_id_name(declaration_full_name.as_ref()); + + let mut guid = GUID::default(); + let result = rometadataresolution::ro_get_parameterized_type_instance_iid( + result.1, + result.0.as_mut_ptr(), + Some(GenericInstanceIdBuilder::locator_impl), + &mut guid, + None, + ); + debug_assert!(result.is_ok()); + + return guid; + } +} diff --git a/core/src/metadata/meta_data_reader.rs b/core/src/metadata/meta_data_reader.rs index 629ef98..c003a6c 100644 --- a/core/src/metadata/meta_data_reader.rs +++ b/core/src/metadata/meta_data_reader.rs @@ -1,4 +1,4 @@ -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, RwLock}; use windows::HSTRING; @@ -23,18 +23,18 @@ const SYSTEM_MULTICASTDELEGATE: &str = "System.MulticastDelegate"; pub struct MetadataReader {} impl MetadataReader { - pub fn find_by_name_w(full_name: PCWSTR) -> Option>> { + pub fn find_by_name_w(full_name: PCWSTR) -> Option>> { let mut count = 0; helpers::to_string_length(full_name, &mut count); let slice = unsafe { std::slice::from_raw_parts(full_name, count) }; let name = OsString::from_wide(slice).to_string_lossy(); MetadataReader::find_by_name(name.as_ref()) } - pub fn find_by_name(full_name: &str) -> Option>> { + pub fn find_by_name(full_name: &str) -> Option>> { if full_name.is_empty() { return Some( Arc::new( - Mutex::new(NamespaceDeclaration::new("")) + RwLock::new(NamespaceDeclaration::new("")) ) ); } @@ -50,18 +50,23 @@ impl MetadataReader { if get_metadata_file_result == windows::HRESULT::from_win32(RO_E_METADATA_NAME_IS_NAMESPACE as u32) { return Some( Arc::new( - Mutex::new(NamespaceDeclaration::new(full_name)) + RwLock::new(NamespaceDeclaration::new(full_name)) ) ); } return None; } + let mut metadata = unsafe { metadata.assume_init() }; + let mut flags = 0; let mut parent_token = mdTokenNil; - debug_assert!(imeta_data_import2::get_type_def_props( - metadata.as_mut_ptr(), token, None, None, None, Some(&mut flags), Some(&mut parent_token), - ).is_ok()); + { + let result = imeta_data_import2::get_type_def_props( + &mut metadata, token, None, None, None, Some(&mut flags), Some(&mut parent_token), + ); + debug_assert!(result.is_ok()); + } if helpers::is_td_class(flags) { @@ -69,37 +74,39 @@ impl MetadataReader { match CorTokenType::from(enums::type_from_token(parent_token)) { CorTokenType::mdtTypeDef => { + let result = imeta_data_import2::get_type_def_props( + &mut metadata, parent_token, Some(&mut parent_name), Some(parent_name.len() as u32), + None, None, None, + ); debug_assert!( - imeta_data_import2::get_type_def_props( - metadata.as_mut_ptr(), parent_token, Some(parent_name.as_mut_ptr()), Some(parent_name.len() as u32), - None, None, None, - ).is_ok() + result.is_ok() ); } CorTokenType::mdtTypeRef => { + let result = imeta_data_import2::get_type_ref_props( + &mut metadata, parent_token, None, Some(&mut parent_name), Some(parent_name.len() as u32), None, + ); debug_assert!( - imeta_data_import2::get_type_ref_props( - metadata.as_mut_ptr(), parent_token, None, Some(parent_name.as_mut_ptr()), Some(parent_name.len() as u32), None, - ).is_ok() - ) + result.is_ok() + ); } _ => { - std::unreachable!() + core_unreachable() } } let mut parent_name_string = OsString::from_wide(&parent_name).to_string_lossy().as_ref(); let metadata = unsafe { Arc::new( - Mutex::new( - metadata.assume_init() + RwLock::new( + metadata ) ) }; if parent_name_string == SYSTEM_ENUM { return Some( Arc::new( - Mutex::new(EnumDeclaration::new(metadata, token)) + RwLock::new(EnumDeclaration::new(Some(metadata), token)) ) ); } @@ -107,7 +114,7 @@ impl MetadataReader { if parent_name_string == SYSTEM_VALUETYPE { return Some( Arc::new( - Mutex::new(StructDeclaration::new(metadata, token)) + RwLock::new(StructDeclaration::new(Some(metadata), token)) ) ); } @@ -116,13 +123,13 @@ impl MetadataReader { return if full_name.contains("`") { Some( Arc::new( - Mutex::new(GenericDelegateDeclaration::new(metadata, token)) + RwLock::new(GenericDelegateDeclaration::new(Some(metadata), token)) ) ) } else { Some( Arc::new( - Mutex::new(DelegateDeclaration::new(metadata, token)) + RwLock::new(DelegateDeclaration::new(Some(metadata), token)) ) ) } @@ -130,7 +137,7 @@ impl MetadataReader { return Some( Arc::new( - Mutex::new(ClassDeclaration::new(metadata, token)) + RwLock::new(ClassDeclaration::new(Some(metadata), token)) ) ); } @@ -138,15 +145,15 @@ impl MetadataReader { if helpers::is_td_interface(flags) { let metadata = unsafe { Arc::new( - Mutex::new( - metadata.assume_init() + RwLock::new( + metadata ) ) }; return if full_name.contains("`") { Some( Arc::new( - Mutex::new(GenericInterfaceDeclaration::new(metadata, token)) + RwLock::new(GenericInterfaceDeclaration::new(metadata, token)) ) ) } else { diff --git a/core/src/metadata/signature.rs b/core/src/metadata/signature.rs index dffc864..10b2c37 100644 --- a/core/src/metadata/signature.rs +++ b/core/src/metadata/signature.rs @@ -1,155 +1,160 @@ #![allow(non_upper_case_globals)] -use crate::prelude::*; use crate::bindings::helpers; +use crate::prelude::*; use std::borrow::Cow; - const Guid: &str = "Guid"; #[derive(Debug)] pub struct Signature {} impl Signature { - pub fn consume_type(signature: PCCOR_SIGNATURE) -> PCCOR_SIGNATURE { - let start = signature; - let element_type = helpers::cor_sig_uncompress_element_type(signature); - use crate::enums::CorElementType; - match element_type { - CorElementType::ElementTypeVoid | - CorElementType::ElementTypeBoolean | - CorElementType::ElementTypeChar | - CorElementType::ElementTypeI1 | - CorElementType::ElementTypeU1 | - CorElementType::ElementTypeI2 | - CorElementType::ElementTypeU2 | - CorElementType::ElementTypeI4 | - CorElementType::ElementTypeU4 | - CorElementType::ElementTypeI8 | - CorElementType::ElementTypeU8 | - CorElementType::ElementTypeR4 | - CorElementType::ElementTypeR8 | - CorElementType::ElementTypeString => start, - CorElementType::ElementTypeValuetype => { - helpers::cor_sig_uncompress_token(signature); - start - } - CorElementType::ElementTypeClass => { - helpers::cor_sig_uncompress_token(signature); - start - } - CorElementType::ElementTypeObject => start, - CorElementType::ElementTypeSzarray => { - Signature::consume_type(signature); - start - } - CorElementType::ElementTypeVar => { - helpers::cor_sig_uncompress_data(signature); - start - } - CorElementType::ElementTypeGenericinst => { - helpers::cor_sig_uncompress_element_type(signature); - helpers::cor_sig_uncompress_token(signature); - - let generic_arguments_count = helpers::cor_sig_uncompress_data(signature); - for i in 0..generic_arguments_count { - Signature::consume_type(signature); - } - start - } - CorElementType::ElementTypeByref => { - Signature::consume_type(signature); - start - } - _ => { - std::unreachable!() - } - } - } - - pub fn to_string<'a>(metadata: *mut IMetaDataImport2, signature: PCCOR_SIGNATURE) -> Cow<'a, str> { - let element_type = helpers::cor_sig_uncompress_element_type(signature); - use crate::enums::CorElementType; - return match element_type { - CorElementType::ElementTypeVoid => "Void".into(), - CorElementType::ElementTypeBoolean => "Boolean".into(), - CorElementType::ElementTypeChar => "Char16".into(), - CorElementType::ElementTypeI1 => "Int8".into(), - CorElementType::ElementTypeU1 => "UInt8".into(), - CorElementType::ElementTypeI2 => "Int16".into(), - CorElementType::ElementTypeU2 => "UInt16".into(), - CorElementType::ElementTypeI4 => "Int32".into(), - CorElementType::ElementTypeU4 => "UInt32".into(), - CorElementType::ElementTypeI8 => "Int64".into(), - CorElementType::ElementTypeU8 => "UInt64".into(), - CorElementType::ElementTypeR4 => "Single".into(), - CorElementType::ElementTypeR8 => "Double".into(), - CorElementType::ElementTypeString => "String".into(), - CorElementType::ElementTypeValuetype => { - let token = helpers::cor_sig_uncompress_token(signature); - let mut class_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; - let length = helpers::get_type_name(metadata, token, class_name_data.as_mut_ptr(), class_name_data.len() as u32); - - let class_name = OsString::from_wide(&class_name_data[..length as usize]).to_string_lossy().as_ref(); - if class_name.eq("System.Guid") { - Guid.into() - } else { - class_name.into() - } - } - CorElementType::ElementTypeClass => { - let token = helpers::cor_sig_uncompress_token(signature); - let mut class_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; - let length = helpers::get_type_name(metadata, token, class_name_data.as_mut_ptr(), class_name_data.len() as u32); - OsString::from_wide(&class_name_data[..length as usize]).to_string_lossy() - } - CorElementType::ElementTypeObject => "Object".into(), - CorElementType::ElementTypeSzarray => { - let result = Signature::to_string(metadata, signature); - (result.to_owned() + "[]").into() - } - CorElementType::ElementTypeVar => { - let index = helpers::cor_sig_uncompress_data(signature); - let mut result_data = [0_u16; MAX_IDENTIFIER_LENGTH]; - let length = helpers::to_wstring(index, result_data.as_mut_ptr()); - ("Var!".to_owned() + OsString::from_wide(&result_data[..length as usize]).to_string_lossy().as_ref()).into() - } - CorElementType::ElementTypeGenericinst => { - let generic_type = helpers::cor_sig_uncompress_element_type(signature); - debug_assert!(generic_type == CorElementType::ElementTypeClass); - - let token = helpers::cor_sig_uncompress_token(signature); - - - let mut class_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; - let length = helpers::get_type_name(metadata, token, class_name_data.as_mut_ptr(), class_name_data.len() as u32); - - let mut result = OsString::from_wide(&class_name_data[..length as usize]).to_string_lossy().as_ref().to_owned(); - - result += "<"; - - let generic_arguments_count = helpers::cor_sig_uncompress_data(signature); - for i in 0..generic_arguments_count { - let sig_type = Signature::consume_type(signature); - let data = Signature::to_string(metadata, sig_type); - result += data.as_ref(); - if i == generic_arguments_count - 1 { - result += ", "; - } - } - - result += ">"; - - result.into() - } - CorElementType::ElementTypeByref => { - let mut result = "ByRef ".to_owned(); - result += Signature::to_string(metadata, signature).as_ref(); - result.into() - } - _ => { - std::unreachable!() - } - }; - } -} \ No newline at end of file + pub fn consume_type(signature: PCCOR_SIGNATURE) -> PCCOR_SIGNATURE { + let start = signature; + let element_type = helpers::cor_sig_uncompress_element_type(signature); + use crate::enums::CorElementType; + match element_type { + CorElementType::ElementTypeVoid + | CorElementType::ElementTypeBoolean + | CorElementType::ElementTypeChar + | CorElementType::ElementTypeI1 + | CorElementType::ElementTypeU1 + | CorElementType::ElementTypeI2 + | CorElementType::ElementTypeU2 + | CorElementType::ElementTypeI4 + | CorElementType::ElementTypeU4 + | CorElementType::ElementTypeI8 + | CorElementType::ElementTypeU8 + | CorElementType::ElementTypeR4 + | CorElementType::ElementTypeR8 + | CorElementType::ElementTypeString => start, + CorElementType::ElementTypeValuetype => { + helpers::cor_sig_uncompress_token(signature); + start + } + CorElementType::ElementTypeClass => { + helpers::cor_sig_uncompress_token(signature); + start + } + CorElementType::ElementTypeObject => start, + CorElementType::ElementTypeSzarray => { + Signature::consume_type(signature); + start + } + CorElementType::ElementTypeVar => { + helpers::cor_sig_uncompress_data(signature); + start + } + CorElementType::ElementTypeGenericinst => { + helpers::cor_sig_uncompress_element_type(signature); + helpers::cor_sig_uncompress_token(signature); + + let generic_arguments_count = helpers::cor_sig_uncompress_data(signature); + for i in 0..generic_arguments_count { + Signature::consume_type(signature); + } + start + } + CorElementType::ElementTypeByref => { + Signature::consume_type(signature); + start + } + _ => { + std::unreachable!() + } + } + } + + pub fn to_string<'a>(metadata: &IMetaDataImport2, signature: PCCOR_SIGNATURE) -> Cow<'a, str> { + let element_type = helpers::cor_sig_uncompress_element_type(signature); + return match element_type { + CorElementType::ElementTypeVoid => "Void".into(), + CorElementType::ElementTypeBoolean => "Boolean".into(), + CorElementType::ElementTypeChar => "Char16".into(), + CorElementType::ElementTypeI1 => "Int8".into(), + CorElementType::ElementTypeU1 => "UInt8".into(), + CorElementType::ElementTypeI2 => "Int16".into(), + CorElementType::ElementTypeU2 => "UInt16".into(), + CorElementType::ElementTypeI4 => "Int32".into(), + CorElementType::ElementTypeU4 => "UInt32".into(), + CorElementType::ElementTypeI8 => "Int64".into(), + CorElementType::ElementTypeU8 => "UInt64".into(), + CorElementType::ElementTypeR4 => "Single".into(), + CorElementType::ElementTypeR8 => "Double".into(), + CorElementType::ElementTypeString => "String".into(), + CorElementType::ElementTypeValuetype => { + let token = helpers::cor_sig_uncompress_token(signature); + let mut class_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; + let length = helpers::get_type_name(metadata, token, &mut class_name_data); + + let class_name = OsString::from_wide(&class_name_data[..length as usize]) + .to_string_lossy() + .as_ref(); + if class_name.eq("System.Guid") { + Guid.into() + } else { + class_name.into() + } + } + CorElementType::ElementTypeClass => { + let token = helpers::cor_sig_uncompress_token(signature); + let mut class_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; + let length = helpers::get_type_name(metadata, token, &mut class_name_data); + OsString::from_wide(&class_name_data[..length as usize]).to_string_lossy() + } + CorElementType::ElementTypeObject => "Object".into(), + CorElementType::ElementTypeSzarray => { + let result = Signature::to_string(metadata, signature); + (result.to_owned() + "[]").into() + } + CorElementType::ElementTypeVar => { + let index = helpers::cor_sig_uncompress_data(signature); + let mut result_data = [0_u16; MAX_IDENTIFIER_LENGTH]; + let length = helpers::to_wstring(index, &mut result_data); + ("Var!".to_owned() + + OsString::from_wide(&result_data[..length as usize]) + .to_string_lossy() + .as_ref()) + .into() + } + CorElementType::ElementTypeGenericinst => { + let generic_type = helpers::cor_sig_uncompress_element_type(signature); + debug_assert!(generic_type == CorElementType::ElementTypeClass); + + let token = helpers::cor_sig_uncompress_token(signature); + + let mut class_name_data = [0_u16; MAX_IDENTIFIER_LENGTH]; + let length = helpers::get_type_name(metadata, token, &mut class_name_data); + + let mut result = + OsString::from_wide(&class_name_data[..length as usize]).to_string_lossy(); + + result += "<"; + + let generic_arguments_count = helpers::cor_sig_uncompress_data(signature); + for i in 0..generic_arguments_count { + let sig_type = Signature::consume_type(signature); + let data = Signature::to_string(metadata, sig_type); + result += data.as_ref(); + if i == generic_arguments_count - 1 { + result += ", "; + } + } + + result += ">"; + + result.into() + } + CorElementType::ElementTypeByref => { + let mut result = "ByRef ".to_owned(); + result += Signature::to_string(metadata, signature).as_ref(); + result.into() + } + _ => { + core_unreachable(); + Cow::default() + } + }; + } +} diff --git a/core/src/prelude.rs b/core/src/prelude.rs index c0a90fc..01bbe35 100644 --- a/core/src/prelude.rs +++ b/core/src/prelude.rs @@ -2,12 +2,31 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] -pub use core_bindings::*; -pub use std::ffi::{OsString}; -pub use std::os::raw::{c_long, c_uint, c_void}; pub use libc::wchar_t; +pub use std::ffi::OsString; +pub use std::os::raw::{c_long, c_uint, c_void}; pub use std::os::windows::ffi::*; +pub use super::enums::*; +pub use core_bindings::{ + mdCustomAttribute, mdEvent, mdFieldDef, mdGenericParam, mdInterfaceImpl, mdMemberRef, + mdMethodDef, mdParamDef, mdProperty, mdToken, mdTypeDef, mdTypeRef, mdTypeSpec, + IMetaDataImport2 as IMetaDataImport2_, BYTE, DWORD, HCORENUM, LPCWSTR, LPWSTR, PCCOR_SIGNATURE, + ULONG, ULONG32, UVCP_CONSTANT, +}; +use core_bindings::{ + Helpers_RO_E_METADATA_NAME_IS_NAMESPACE, Helpers_mdAssemblyNil, Helpers_mdAssemblyRefNil, + Helpers_mdCustomAttributeNil, Helpers_mdEventNil, Helpers_mdExportedTypeNil, + Helpers_mdFieldDefNil, Helpers_mdFileNil, Helpers_mdGenericParamConstraintNil, + Helpers_mdGenericParamNil, Helpers_mdInterfaceImplNil, Helpers_mdManifestResourceNil, + Helpers_mdMemberRefNil, Helpers_mdMethodDefNil, Helpers_mdMethodSpecNil, Helpers_mdModuleNil, + Helpers_mdModuleRefNil, Helpers_mdParamDefNil, Helpers_mdPermissionNil, Helpers_mdPropertyNil, + Helpers_mdSignatureNil, Helpers_mdStringNil, Helpers_mdTokenNil, Helpers_mdTypeDefNil, + Helpers_mdTypeRefNil, Helpers_mdTypeSpecNil, GUID, HRESULT, +}; + +use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard, TryLockError}; + pub const mdTokenNil: mdToken = Helpers_mdTokenNil; pub const mdModuleNil: mdToken = Helpers_mdModuleNil; pub const mdTypeRefNil: mdToken = Helpers_mdTypeRefNil; @@ -34,32 +53,45 @@ pub const mdGenericParamConstraintNil: mdToken = Helpers_mdGenericParamConstrain pub const mdMethodSpecNil: mdToken = Helpers_mdMethodSpecNil; pub const mdStringNil: mdToken = Helpers_mdStringNil; -pub use super::enums::*; -use std::sync::{Arc, Mutex}; - - pub type CLSID = GUID; pub const RO_E_METADATA_NAME_IS_NAMESPACE: HRESULT = Helpers_RO_E_METADATA_NAME_IS_NAMESPACE; pub const MAX_IDENTIFIER_LENGTH: usize = 511; - pub const COR_CTOR_METHOD_NAME: &str = ".ctor"; pub const COR_CCTOR_METHOD_NAME: &str = ".cctor"; pub const COR_ENUM_FIELD_NAME: &str = "value__"; +pub fn get_lock_value<'a, T>(value: &Option>>) -> Option<&T> { + match Option::as_ref(&value) { + None => None, + Some(value) => match value.try_read() { + Ok(value) => Some(&*value), + Err(_) => None, + }, + } +} -pub fn get_mutex_value_mut<'a, T>(value: &Arc>) -> &mut T { - match value.lock() { - Ok(value) => &mut *value, - Err(poisoned) => &mut *poisoned.into_inner() - } +pub fn get_mutex_value_mut<'a, T>(value: &Option>>) -> Option<&mut T> { + match Option::as_ref(&value) { + None => None, + Some(value) => match value.try_write() { + Ok(value) => Some(&mut *value), + Err(_) => None, + }, + } } -pub fn get_mutex_value<'a, T>(value: &Arc>) -> &T { - match value.lock() { - Ok(value) => &*value, - Err(poisoned) => &*poisoned.into_inner() - } +#[cfg(debug_assertions)] +pub fn core_unreachable() { + std::unreachable!() } + + +#[cfg(debug_assertions)] +pub fn core_unimplemented() { + std::unimplemented!() +} + +pub use crate::bindings::imeta_data_import2::*; diff --git a/core/src/runtime/com/com_constructor.rs b/core/src/runtime/com/com_constructor.rs index ac1d974..3fb7142 100644 --- a/core/src/runtime/com/com_constructor.rs +++ b/core/src/runtime/com/com_constructor.rs @@ -1,2 +1,17 @@ +use crate::prelude::*; +use crate::metadata::declaring_interface_for_method::Metadata; + + #[derive(Debug)] -pub struct COMConstructor {} \ No newline at end of file +pub struct COMConstructor {} + +#[derive(Debug)] +pub struct COMConstructorCall { + initialization: Initialization, +} + +impl COMConstructorCall { + pub fn new() -> Self { + Metadata::find_declaring_interface_for_method() + } +} \ No newline at end of file diff --git a/core/src/runtime/com/com_interop.rs b/core/src/runtime/com/com_interop.rs index eedd2c5..f51f7d8 100644 --- a/core/src/runtime/com/com_interop.rs +++ b/core/src/runtime/com/com_interop.rs @@ -1,6 +1,24 @@ +use crate::metadata::meta_data_reader::MetadataReader; +use crate::prelude::{ get_lock_value}; + #[derive(Debug)] pub struct COMInterop {} impl COMInterop { - pub fn resolve_type(type_name: &str) {} + pub fn new() -> Self { + Self {} + } + pub fn resolve_type(type_name: &str) { + let decl = MetadataReader::find_by_name(type_name); + println!("{:?}",decl); + /*if let Some(decl) = decl { + if let Some(decl) = decl.try_read() { + + } + decl.try_read().unwrap() + let val = get_lock_value(decl); + val.kind() + } + */ + } } \ No newline at end of file diff --git a/core/src/runtime/ffi/ffi_interop.rs b/core/src/runtime/ffi/ffi_interop.rs index 18332fb..1d0bbc7 100644 --- a/core/src/runtime/ffi/ffi_interop.rs +++ b/core/src/runtime/ffi/ffi_interop.rs @@ -1 +1,2 @@ +#[derive(Debug)] pub struct FFIInterop {} \ No newline at end of file diff --git a/core/src/runtime/mod.rs b/core/src/runtime/mod.rs index 132ebc3..5151836 100755 --- a/core/src/runtime/mod.rs +++ b/core/src/runtime/mod.rs @@ -11,11 +11,13 @@ use std::os::windows::prelude::*; use std::path::{Path, PathBuf}; use windows::HSTRING; use crate::runtime::com::com_interop::COMInterop; +use rusty_v8::{Value, Local, Handle}; +use std::convert::TryInto; pub struct Runtime { - isolate: v8::OwnedIsolate, - global_context: v8::Global, - app_root: String, + isolate: v8::OwnedIsolate, + global_context: v8::Global, + app_root: String, } @@ -23,206 +25,208 @@ const MAX_IDENTIFIER_LENGTH: usize = 511; impl Runtime { - pub fn new(app_root: &str) -> Self { - let platform = v8::new_default_platform().unwrap(); - v8::V8::initialize_platform(platform); - v8::V8::initialize(); - let mut isolate = v8::Isolate::new(Default::default()); - - isolate.set_capture_stack_trace_for_uncaught_exceptions(true, 100); - - let global_context; - { - let mut scope = &mut v8::HandleScope::new(&mut isolate); - let mut global = v8::FunctionTemplate::new(scope, Runtime::handle_global); - - { - let class_name = v8::String::new(scope, "NativeScriptGlobalObject").unwrap(); - global.set_class_name(class_name); + pub fn new(app_root: &str) -> Self { + let platform = v8::new_default_platform().unwrap(); + v8::V8::initialize_platform(platform); + v8::V8::initialize(); + let mut isolate = v8::Isolate::new(Default::default()); + + isolate.set_capture_stack_trace_for_uncaught_exceptions(true, 100); + + let global_context; + { + let mut scope = &mut v8::HandleScope::new(&mut isolate); + let mut global = v8::FunctionTemplate::new(scope, Runtime::handle_global); + + { + let class_name = v8::String::new(scope, "NativeScriptGlobalObject").unwrap(); + global.set_class_name(class_name); + } + + let mut global_template = v8::ObjectTemplate::new_from_template(scope, global); + + global_template.set_internal_field_count(0); + + { + { + Runtime::init_performance(scope, &mut global_template); + } + + { + Runtime::init_time(scope, &mut global_template); + } + + + let mut context = v8::Context::new_from_template(scope, global_template); + + let mut local_scope = v8::ContextScope::new(scope, context); + + { + Runtime::init_global(&mut local_scope, context); + } + + { + Runtime::init_console(&mut local_scope, context); + } + + { + Runtime::init_meta(&mut local_scope, context); + } + + { + global_context = v8::Global::new(&mut local_scope, context); + } + } + } + + Self { + isolate, + global_context, + app_root: app_root.to_string(), + } + } + + fn run_script(&mut self, script: &str) { + /* + let path = PathBuf::from(script); + println!("??? {:?}", path.to_string_lossy()); + let mut file = std::fs::File::open(std::fs::canonicalize(&path).unwrap()).unwrap(); + let mut data = Vec::new(); + file.read_to_end(&mut data); + let script = String::from_utf8_lossy(data.as_slice()); + */ + + let mut isolate = &mut self.isolate; + let mut scope = &mut v8::HandleScope::new(isolate); + let mut local = v8::Local::new(scope, &self.global_context); + let mut scope = &mut v8::ContextScope::new(scope, local); + let code = v8::String::new(scope, script).unwrap(); + let script = v8::Script::compile(&mut scope, code, None).unwrap(); + let result = script.run(&mut scope).unwrap(); + let result = result.to_string(&mut scope).unwrap(); + } + + fn handle_global(_scope: &mut v8::HandleScope, _args: v8::FunctionCallbackArguments, _retval: v8::ReturnValue) {} + + fn init_global(scope: &mut v8::ContextScope>, context: v8::Local) { + let mut global = context.global(scope); + let value = v8::String::new( + scope, "global", + ).unwrap().into(); + global.define_own_property(scope, value, global.into(), v8::READ_ONLY); + let interop = Box::new(COMInterop::new()); + let interop = Box::into_raw(interop); + let value = v8::External::new(scope, interop as *mut c_void); + global.set_internal_field(0, value.into()); + } + + fn init_console(scope: &mut v8::ContextScope>, context: v8::Local) { + let console = v8::Object::new(scope); + let log = v8::Function::new(scope, console::handle_console_log).unwrap(); + let dir = v8::Function::new(scope, console::handle_console_dir).unwrap(); + + { + let name = v8::String::new(scope, "log").unwrap().into(); + console.set( + scope, + name, + log.into(), + ); + } + + { + let name = v8::String::new(scope, "dir").unwrap().into(); + console.set( + scope, + name, + dir.into(), + ); + } + + let mut global = context.global(scope); + let value = v8::String::new( + scope, "console", + ).unwrap().into(); + global.define_own_property(scope, value, console.into(), v8::READ_ONLY); + } + + fn handle_time(scope: &mut v8::HandleScope, + _args: v8::FunctionCallbackArguments, + mut retval: v8::ReturnValue) { + let now = chrono::Utc::now(); + retval.set( + v8::Number::new(scope, (now.timestamp_millis() / 1000000) as f64).into() + ) + } + + fn init_time(scope: &mut v8::HandleScope<()>, global: &mut v8::Local) { + let time = v8::FunctionTemplate::new(scope, Runtime::handle_time); + global.set( + v8::String::new(scope, "time").unwrap().into(), time.into(), + ); + } + + fn init_performance(scope: &mut v8::HandleScope<()>, global: &mut v8::Local) { + let performance = v8::ObjectTemplate::new(scope); + let now = v8::FunctionTemplate::new(scope, Runtime::handle_now); + performance.set( + v8::String::new(scope, "now").unwrap().into(), + now.into(), + ); + global.set( + v8::String::new(scope, "performance").unwrap().into(), + performance.into(), + ); + } + + fn handle_now(scope: &mut v8::HandleScope, + _args: v8::FunctionCallbackArguments, + mut retval: v8::ReturnValue) { + let now = chrono::Utc::now(); + retval.set( + v8::Number::new(scope, now.timestamp_nanos() as f64).into() + ) + } + + fn init_meta(scope: &mut v8::ContextScope>, context: v8::Local) { + let meta = v8::Function::new(scope, Runtime::handle_meta).unwrap(); + let mut global = context.global(scope); + let value = v8::String::new( + scope, "$", + ).unwrap().into(); + global.define_own_property(scope, value, meta.into(), v8::READ_ONLY); + } + + fn handle_meta(scope: &mut v8::HandleScope, + args: v8::FunctionCallbackArguments, + mut retval: v8::ReturnValue) { + println!("handle meta {:?}", args.get(0).to_rust_string_lossy(scope)); + let isolate = scope.get_isolate_mut(); + let class_name = args.get(0).to_rust_string_lossy(scope); + let global = scope.get_current_context().global(scope); + match global.get_internal_field(scope, 0) { + None => {} + Some(value) => { + let interop: v8::External = value.try_into().unwrap(); + let interop = interop.value() as *mut COMInterop; } - - let mut global_template = v8::ObjectTemplate::new_from_template(scope, global); - - global_template.set_internal_field_count(0); - - { - { - Runtime::init_performance(scope, &mut global_template); - } - - { - Runtime::init_time(scope, &mut global_template); - } - - - let mut context = v8::Context::new_from_template(scope, global_template); - - let mut local_scope = v8::ContextScope::new(scope, context); - - { - - Runtime::init_global(&mut local_scope, context); - } - - { - Runtime::init_console(&mut local_scope, context); - } - - { - Runtime::init_meta(&mut local_scope, context); - } - - { - global_context = v8::Global::new(&mut local_scope, context); - } - - } - } - - Self { - isolate, - global_context, - app_root: app_root.to_string(), - } - } - - fn run_script(&mut self, script: &str) { - /* - let path = PathBuf::from(script); - println!("??? {:?}", path.to_string_lossy()); - let mut file = std::fs::File::open(std::fs::canonicalize(&path).unwrap()).unwrap(); - let mut data = Vec::new(); - file.read_to_end(&mut data); - let script = String::from_utf8_lossy(data.as_slice()); - */ - - let mut isolate = &mut self.isolate; - let mut scope = &mut v8::HandleScope::new(isolate); - let mut local = v8::Local::new(scope, &self.global_context); - let mut scope = &mut v8::ContextScope::new(scope, local); - let code = v8::String::new(scope, script).unwrap(); - let script = v8::Script::compile(&mut scope, code, None).unwrap(); - let result = script.run(&mut scope).unwrap(); - let result = result.to_string(&mut scope).unwrap(); - } - - fn handle_global(_scope: &mut v8::HandleScope, _args: v8::FunctionCallbackArguments, _retval: v8::ReturnValue) { - - } - fn init_global(scope: &mut v8::ContextScope>, context: v8::Local) { - let mut global = context.global(scope); - let value = v8::String::new( - scope, "global", - ).unwrap().into(); - global.define_own_property(scope, value, global.into(), v8::READ_ONLY); - let interop = COMInterop - global.set_internal_field(0, ) - } - - fn init_console(scope: &mut v8::ContextScope>, context: v8::Local) { - let console = v8::Object::new(scope); - let log = v8::Function::new(scope, console::handle_console_log).unwrap(); - let dir = v8::Function::new(scope, console::handle_console_dir).unwrap(); - - { - let name = v8::String::new(scope, "log").unwrap().into(); - console.set( - scope, - name, - log.into(), - ); } - - { - let name = v8::String::new(scope, "dir").unwrap().into(); - console.set( - scope, - name, - dir.into(), - ); - } - - let mut global = context.global(scope); - let value = v8::String::new( - scope, "console", - ).unwrap().into(); - global.define_own_property(scope, value, console.into(), v8::READ_ONLY); - } - - fn handle_time(scope: &mut v8::HandleScope, - _args: v8::FunctionCallbackArguments, - mut retval: v8::ReturnValue) { - let now = chrono::Utc::now(); - retval.set( - v8::Number::new(scope, (now.timestamp_millis() / 1000000) as f64).into() - ) - } - - fn init_time(scope: &mut v8::HandleScope<()>, global: &mut v8::Local) { - let time = v8::FunctionTemplate::new(scope, Runtime::handle_time); - global.set( - v8::String::new(scope, "time").unwrap().into(), time.into(), - ); - } - - fn init_performance(scope: &mut v8::HandleScope<()>, global: &mut v8::Local) { - let performance = v8::ObjectTemplate::new(scope); - let now = v8::FunctionTemplate::new(scope, Runtime::handle_now); - performance.set( - v8::String::new(scope, "now").unwrap().into(), - now.into(), - ); - global.set( - v8::String::new(scope, "performance").unwrap().into(), - performance.into(), - ); - } - - fn handle_now(scope: &mut v8::HandleScope, - _args: v8::FunctionCallbackArguments, - mut retval: v8::ReturnValue) { - let now = chrono::Utc::now(); - retval.set( - v8::Number::new(scope, now.timestamp_nanos() as f64).into() - ) - } - - fn init_meta(scope: &mut v8::ContextScope>, context: v8::Local) { - let meta = v8::Function::new(scope, Runtime::handle_meta).unwrap(); - let mut global = context.global(scope); - let value = v8::String::new( - scope, "$", - ).unwrap().into(); - global.define_own_property(scope, value, meta.into(), v8::READ_ONLY); - } - - fn handle_meta(scope: &mut v8::HandleScope, - args: v8::FunctionCallbackArguments, - mut retval: v8::ReturnValue) { - println!("handle meta {:?}", args.get(0).to_rust_string_lossy(scope)); - - let class_name = args.get(0).to_rust_string_lossy(scope); - - let global = scope.get_current_context().global(scope); - let interop = global.get_internal_field(scope, 0); - - - } + } } #[no_mangle] pub extern fn runtime_init(main_entry: *const c_char) -> i64 { - let string = unsafe { CStr::from_ptr(main_entry) }.to_string_lossy(); - Box::into_raw(Box::new(Runtime::new(string.as_ref()))) as i64 + let string = unsafe { CStr::from_ptr(main_entry) }.to_string_lossy(); + Box::into_raw(Box::new(Runtime::new(string.as_ref()))) as i64 } #[no_mangle] pub extern fn runtime_runscript(runtime: i64, script: *const c_char) { - if runtime != 0 { - let mut runtime: *mut Runtime = runtime as _; - let mut runtime = unsafe { &mut *runtime }; - let script = unsafe { CStr::from_ptr(script) }.to_string_lossy(); - runtime.run_script(script.as_ref()); - } + if runtime != 0 { + let mut runtime: *mut Runtime = runtime as _; + let mut runtime = unsafe { &mut *runtime }; + let script = unsafe { CStr::from_ptr(script) }.to_string_lossy(); + runtime.run_script(script.as_ref()); + } } \ No newline at end of file