### Get Computer Name (Two-Step Call with Vec) Source: https://kennykerr.ca/rust-getting-started/string-tutorial.html Demonstrates the two-step process for getting the computer name using `GetComputerNameW`. The first call determines the required buffer size, and the second call populates a `Vec` buffer. This method involves a heap allocation. ```rust #![allow(unused)] fn main() { let mut buff_len = 0u32; unsafe { // this function will return an error code because it // did not actually write the string. This is normal. let e = GetComputerNameW(None, &mut buff_len).unwrap_err(); debug_assert_eq!(e.code(), HRESULT::from(ERROR_BUFFER_OVERFLOW)); } // buff len now has the length of the string (in UTF-16 characters) // the function would like to write. This *includes* the // null terminator. Let's create a vector buffer and feed that to the function. let mut buffer = Vec::::with_capacity(buff_len as usize); unsafe { WindowsProgramming::GetComputerNameW( Some(PWSTR(buffer.as_mut_ptr())), &mut buff_len).unwrap(); // set the vector length // buff_len now includes the size, which *does not include* the null terminator. // let's set the length to just before the terminator so we don't have to worry // about it in later conversions. buffer.set_len(buff_len); } // we can now convert this to a valid Rust string // omitting the null terminator String::from_utf16_lossy(&buffer) } ``` -------------------------------- ### Example Output Source: https://kennykerr.ca/rust-getting-started/calling-your-first-windows-api.html The expected output when running the complete sample code, showing the final count of the incremented counter. ```text counter: 10 ``` -------------------------------- ### Get Computer Name (widestring crate) Source: https://kennykerr.ca/rust-getting-started/string-tutorial.html Demonstrates using the `widestring` crate to work directly with UTF-16 strings. This example retrieves the computer name into a buffer and then creates a `Utf16Str` slice, allowing for direct display or further UTF-16 manipulation without immediate conversion to UTF-8. ```rust #![allow(unused)] fn main() { // for this example, we'll just use an array again let mut name = [0u16; MAX_COMPUTERNAME_LENGTH as usize + 1]; let mut len = name.len() as u32; unsafe { GetComputerNameW( Some(PWSTR(name.as_mut_ptr())), &mut len) .unwrap(); } // we can make a UTF16Str slice directly from the buffer, // without needing to do any copy. This will error if the buffer // isn't valid UTF-16. let wstr = Utf16Str::from_slice(&name[..len as usize]) .unwrap(); // this can be displayed as is. println!("Computer name is {}", wstr); // we can also transfer it into owned string, which can } ``` -------------------------------- ### Add windows-targets and windows-bindgen to Cargo.toml Source: https://kennykerr.ca/rust-getting-started/standalone-code-generation.html Add the windows-targets crate as a regular dependency and windows-bindgen as a dev dependency to your Cargo.toml file. This setup ensures you have the necessary import libraries and the tool for generating bindings. ```toml [dependencies.windows-targets] version = "0.52" [dev-dependencies.windows-bindgen] version = "0.52" ``` -------------------------------- ### Get Computer Name (Array, Single Call) Source: https://kennykerr.ca/rust-getting-started/string-tutorial.html Optimizes getting the computer name by using a fixed-size array, avoiding heap allocation. This is possible because the maximum computer name length is known at compile time. It also skips the two-step call by ensuring the buffer is sufficiently large. ```rust #![allow(unused)] fn main() { // avoid the heap allocation since we already know how big this // buffer needs to be at compile time. let mut name = [0u16; MAX_COMPUTERNAME_LENGTH as usize + 1]; let mut len = name.len() as u32; // we can also skip the two-step call, since we know our buffer // is already larger than any possible computer name unsafe { GetComputerNameW( Some(PWSTR(name.as_mut_ptr())), &mut len) .unwrap(); } // the function writes to len with the number of // UTF-16 characters in the string. We can use this // to slice the buffer. String::from_utf16_lossy(&name[..len as usize]) } ``` -------------------------------- ### Import Windows API Functions in Rust Source: https://kennykerr.ca/rust-getting-started/calling-your-first-windows-api.html Use a 'use' declaration to make Windows API functions and types more accessible in your Rust code. This example imports Result and threading-related types. ```rust #![allow(unused)] fn main() { use windows::{core::Result, Win32::System::Threading::*}; } ``` -------------------------------- ### Get Computer Name (HStringBuilder) Source: https://kennykerr.ca/rust-getting-started/string-tutorial.html Uses `HStringBuilder` from the `windows-strings` crate for a more ergonomic approach to generating strings. This method handles heap allocation and null termination automatically, simplifying the conversion to an `HSTRING` and then a Rust `String`. ```rust #![allow(unused)] fn main() { // pre-allocate a HSTRING buffer on the heap // (you do not need to add one to len for the null terminator, // the hstring builder will handle that automatically) let mut buffer = HStringBuilder::new( MAX_COMPUTERNAME_LENGTH as usize); let mut len = buffer.len() as u32 + 1; unsafe { GetComputerNameW( Some(PWSTR(buffer.as_mut_ptr())), &mut len).unwrap(); } // we can now generate a valid HSTRING from the HStringBuilder let buffer = HSTRING::from(buffer); // and we can now return a rust string from the HSTRING: buffer.to_string_lossy() } ``` -------------------------------- ### Generate Windows Bindings with windows-bindgen Source: https://kennykerr.ca/rust-getting-started/standalone-code-generation.html Write a test function that uses the `windows_bindgen::bindgen` function to generate Rust bindings. Specify the output file, configuration, and filters for the APIs you want to include. This example generates bindings for `GetTickCount`. ```rust #![allow(unused)] fn main() { #[test] fn bindgen() { let args = [ "--out", "src/bindings.rs", "--config", "flatten", "--filter", "Windows.Win32.System.SystemInformation.GetTickCount", ]; windows_bindgen::bindgen(args).unwrap(); } } ``` -------------------------------- ### Use Generated Windows API Bindings Source: https://kennykerr.ca/rust-getting-started/standalone-code-generation.html Import the generated bindings module and call Windows API functions within an unsafe block. This example demonstrates calling the `GetTickCount` function from the generated `bindings.rs` file. ```rust mod bindings; fn main() { unsafe { println!("{}", bindings::GetTickCount()); } } ``` -------------------------------- ### Import necessary modules Source: https://kennykerr.ca/rust-getting-started/calling-your-first-com-api.html Import core types and COM-related modules from the windows crate to facilitate API calls. ```rust use windows::{core::*, Win32::System::Com::*}; ``` -------------------------------- ### Configure windows Crate Dependency Source: https://kennykerr.ca/rust-getting-started/calling-your-first-winrt-api.html Add the windows crate to your Cargo.toml file and enable the necessary feature for Data::Xml::Dom. ```toml [dependencies.windows] version = "0.52" features = [ "Data_Xml_Dom", ] ``` -------------------------------- ### Basic Rust Main Function with Result Source: https://kennykerr.ca/rust-getting-started/calling-your-first-winrt-api.html Set up a main function that returns a Result<()> for automatic error propagation, simplifying WinRT API calls. ```rust fn main() -> Result<()> { Ok(()) } ``` -------------------------------- ### Basic Main Function Structure for Unsafe Operations Source: https://kennykerr.ca/rust-getting-started/calling-your-first-windows-api.html Set up a main function that returns a Result and includes an unsafe block. Many Windows API calls are inherently unsafe and require this explicit block. ```rust __ fn main() -> Result<()> { unsafe { } Ok(()) } ``` -------------------------------- ### Call Windows APIs Source: https://kennykerr.ca/rust-getting-started/understanding-windows-targets.html Make calls to Windows APIs after defining them using the `link` macro. Ensure these calls are within an `unsafe` block as they interact with external system functions. ```rust fn main() { unsafe { SetLastError(1234); assert_eq!(GetLastError(), 1234); } } ``` -------------------------------- ### Add windows-targets to Cargo.toml Source: https://kennykerr.ca/rust-getting-started/understanding-windows-targets.html Add this to your Cargo.toml file to include the windows-targets crate for linker support. ```toml [dependencies.windows-targets] version = "0.52" ``` -------------------------------- ### Add windows crate dependency Source: https://kennykerr.ca/rust-getting-started/calling-your-first-com-api.html Configure your Cargo.toml to include the windows crate with the necessary features for COM interop. ```toml [dependencies.windows] version = "0.52" features = [ "Win32_System_Com", ] ``` -------------------------------- ### Import WinRT APIs in Rust Source: https://kennykerr.ca/rust-getting-started/calling-your-first-winrt-api.html Use a 'use' declaration to make WinRT APIs like XmlDocument and core helpers more accessible in your Rust code. ```rust use windows::{core::*, Data::Xml::Dom::XmlDocument}; ``` -------------------------------- ### Add Windows Crate Dependency Source: https://kennykerr.ca/rust-getting-started/calling-your-first-windows-api.html Specify the 'windows' crate and required features in your Cargo.toml file. Features like Win32_Foundation and Win32_System_Threading are common for Windows API interactions. ```toml [dependencies.windows] version = "0.52" features = [ "Win32_Foundation", "Win32_System_Threading", ] ``` -------------------------------- ### Create a new XmlDocument Instance Source: https://kennykerr.ca/rust-getting-started/calling-your-first-winrt-api.html Instantiate an XmlDocument object using its 'new' method. WinRT calls are generally safe and do not require an 'unsafe' block. ```rust let doc = XmlDocument::new()?; ``` -------------------------------- ### Define a C-Style Callback Function Source: https://kennykerr.ca/rust-getting-started/calling-your-first-windows-api.html Implement a callback function with the 'extern "system"' ABI. This function will be executed by the thread pool and should handle shared state safely, like incrementing a RwLock-protected counter. ```rust #![allow(unused)] fn main() { extern "system" fn callback(_: PTP_CALLBACK_INSTANCE, _: *mut std::ffi::c_void, _: PTP_WORK) { let mut counter = COUNTER.write().unwrap(); *counter += 1; } } ``` -------------------------------- ### Call MessageBoxW with HSTRING literals Source: https://kennykerr.ca/rust-getting-started/string-tutorial.html Use the h! macro from 'windows-strings' to create HSTRINGs from string literals for calling Windows APIs. This handles null termination and UTF-16 conversion. ```rust #![allow(unused)] fn main() { // use string literals when calling a message box. let text = h!("Hello from rust!"); let caption = h!("From Rust"); unsafe { // call the MessageBox function and return MESSAGEBOX_RESULT UI::WindowsAndMessaging::MessageBoxW(None, text, caption, UI::WindowsAndMessaging::MESSAGEBOX_STYLE(0) // message box OK ) } } ``` -------------------------------- ### Call MessageBoxW with manually converted Rust strings Source: https://kennykerr.ca/rust-getting-started/string-tutorial.html Manually convert Rust strings to UTF-16 byte vectors with null terminators to call Windows APIs. This method is more verbose than using macros. ```rust #![allow(unused)] fn main() { // this works for any &str, not just literals let text = "I am a message to display!"; let caption = "Message from Rust!"; // convert our text and caption to UTF-16 bytes, // add null terminators using chain, and then collect // the result into a vec let text = text.encode_utf16() .chain(iter::once(0u16)) .collect::>(); let caption = caption.encode_utf16() .chain(iter::once(0u16)) .collect::>(); // call the API, wrapping our vec pointer in a PCWSTR struct. unsafe { UI::WindowsAndMessaging::MessageBoxW(None, PCWSTR(text.as_ptr()), PCWSTR(caption.as_ptr()), UI::WindowsAndMessaging::MESSAGEBOX_STYLE(0) // message box OK ) } } ``` -------------------------------- ### Call MessageBoxW with HSTRING from Rust strings Source: https://kennykerr.ca/rust-getting-started/string-tutorial.html Use HSTRING::from() to convert Rust strings to HSTRINGs, which can be used directly with Windows APIs expecting PCWSTR. This simplifies UTF-16 conversion and null termination. ```rust #![allow(unused)] fn main() { let text = "I am a message to display!"; let caption = "Message from Rust!"; // convert our strings into UTF-16 // this incurrs a performance cost because there is a copy + conversion // from the standard rust utf-8 string. // we are using HSTRING, which is an immutable UTF-16 string // in the windows-strings crate. It can be generated from a standard // rust string, and it can be used in place of a PCWSTR anywhere in the // windows API. unsafe { UI::WindowsAndMessaging::MessageBoxW(None, &HSTRING::from(text), &HSTRING::from(caption), UI::WindowsAndMessaging::MESSAGEBOX_STYLE(0) // message box OK ) } } ``` -------------------------------- ### Inspect IUri interface methods Source: https://kennykerr.ca/rust-getting-started/calling-your-first-com-api.html Call methods like GetDomain and GetPort on the IUri interface to retrieve URI components. These methods invoke virtual functions through the COM interface. ```rust let domain = uri.GetDomain()?; let port = uri.GetPort()?; println!("{domain} ({port})"); ``` -------------------------------- ### Rust Implementation of CreateJsonValidator API Source: https://kennykerr.ca/rust-getting-started/implement-win32-api.html This function serves as the entry point for the CreateJsonValidator API, translating the HRESULT return type to a standard Rust Result for internal error handling. ```rust #![allow(unused)] fn main() { #[no_mangle] unsafe extern "system" fn CreateJsonValidator( schema: *const u8, schema_len: usize, handle: *mut usize, ) -> HRESULT { create_validator(schema, schema_len, handle).into() } } ``` -------------------------------- ### Call CreateUri function Source: https://kennykerr.ca/rust-getting-started/calling-your-first-com-api.html Use the CreateUri function to parse a URI string into an IUri interface. The w! macro is used for null-terminated wide strings. ```rust let uri = CreateUri(w!("http://kennykerr.ca"), Uri_CREATE_CANONICALIZE, 0)?; ``` -------------------------------- ### Cargo.toml for JSON Validator Project Source: https://kennykerr.ca/rust-getting-started/implement-win32-api.html This Cargo.toml file configures the Rust project for building a dynamic library (cdylib) and specifies dependencies for JSON parsing and Windows API support. ```toml [package] name = "json_validator" edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] jsonschema = "0.17" serde_json = "1.0" [dependencies.windows] version = "0.52" features = [ "Win32_Foundation", "Win32_System_Com", ] ``` -------------------------------- ### Helper Function for Parsing Raw JSON Data Source: https://kennykerr.ca/rust-getting-started/implement-win32-api.html Safely parses raw byte slices into `serde_json::Value`, handling null pointers and UTF-8 conversion errors. It maps underlying errors to Windows HRESULTs. ```rust #![allow(unused)] fn main() { unsafe fn json_from_raw_parts(value: *const u8, value_len: usize) -> Result { if value.is_null() { return Err(E_POINTER.into()); } let value = std::slice::from_raw_parts(value, value_len); let value = std::str::from_utf8(value).map_err(|_| Error::from(ERROR_NO_UNICODE_TRANSLATION))?; serde_json::from_str(value).map_err(|error| Error::new(E_INVALIDARG, format!("{error}").into())) } } ``` -------------------------------- ### Define External Functions with link Macro Source: https://kennykerr.ca/rust-getting-started/understanding-windows-targets.html Use the `link` macro to declare external functions from DLLs that your Rust code will call. This macro handles the necessary linker configurations. ```rust #![allow(unused)] fn main() { windows_targets::link!("kernel32.dll" "system" fn SetLastError(code: u32)); windows_targets::link!("kernel32.dll" "system" fn GetLastError() -> u32); } ``` -------------------------------- ### Validate JSON Function Entry Point Source: https://kennykerr.ca/rust-getting-started/implement-win32-api.html Public entry point for validating a JSON value against a compiled schema. Forwards the call to the internal `validate` function and converts the result to HRESULT. ```rust #![allow(unused)] fn main() { #[no_mangle] unsafe extern "system" fn ValidateJson( handle: usize, value: *const u8, value_len: usize, sanitized_value: *mut *mut u8, sanitized_value_len: *mut usize, ) -> HRESULT { validate( handle, value, value_len, sanitized_value, sanitized_value_len, ) .into() } } ``` -------------------------------- ### Rust Use Declarations for JSON Validator Source: https://kennykerr.ca/rust-getting-started/implement-win32-api.html Imports necessary types and traits from the `jsonschema`, `windows`, and standard library for implementing the JSON validator API. ```rust #![allow(unused)] fn main() { use jsonschema::JSONSchema; use windows::{core::*, Win32::Foundation::*, Win32::System::Com::*}; } ``` -------------------------------- ### Basic unsafe block for COM calls Source: https://kennykerr.ca/rust-getting-started/calling-your-first-com-api.html Wrap COM API calls within an unsafe block, as they involve foreign function interfaces. ```rust fn main() -> Result<()> { unsafe { Ok(()) } } ``` -------------------------------- ### Load XML String into XmlDocument Source: https://kennykerr.ca/rust-getting-started/calling-your-first-winrt-api.html Use the LoadXml method to parse an XML string. The 'h!' macro is provided by the windows crate for creating HSTRINGs. ```rust doc.LoadXml(h!("hello world"))?; ``` -------------------------------- ### Return First Error in Rust Source: https://kennykerr.ca/rust-getting-started/implement-win32-api.html This snippet demonstrates how to return the first error from a collection of errors, commonly used in validation scenarios. ```rust Err(Error::new(E_INVALIDARG, message.into())) } ``` -------------------------------- ### Append to Utf16String in Rust Source: https://kennykerr.ca/rust-getting-started/string-tutorial.html Demonstrates appending a string literal to a Utf16String using the '+' operator and a macro for efficient conversion. ```rust let mut wstring = Utf16String::from(wstr); // let's append another string. We'll use a macro to avoid // any UTF conversion at runtime. wstring = wstring + utf16str!("!!!"); ``` -------------------------------- ### Initialize a Shared Counter with RwLock Source: https://kennykerr.ca/rust-getting-started/calling-your-first-windows-api.html Declare a static counter protected by a RwLock for safe concurrent access from multiple threads. This is essential when using thread pools for shared mutable state. ```rust #![allow(unused)] fn main() { static COUNTER: std::sync::RwLock = std::sync::RwLock::new(0); } ``` -------------------------------- ### Create JSON Validator Function Source: https://kennykerr.ca/rust-getting-started/implement-win32-api.html Compiles a JSON schema from raw parts into a usable validator handle. Handles null pointers and invalid schema formats, returning a boxed compiled schema on success. ```rust #![allow(unused)] fn main() { unsafe fn create_validator(schema: *const u8, schema_len: usize, handle: *mut usize) -> Result<()> { let schema = json_from_raw_parts(schema, schema_len)?; let compiled = JSONSchema::compile(&schema) .map_err(|error| Error::new(E_INVALIDARG, error.to_string().into()))?; if handle.is_null() { return Err(E_POINTER.into()); } *handle = Box::into_raw(Box::new(compiled)) as usize; Ok(()) } } ``` -------------------------------- ### Inspect XmlDocument Element Source: https://kennykerr.ca/rust-getting-started/calling-your-first-winrt-api.html Retrieve the document element, assert its node name, and print its inner text. These methods invoke virtual functions through COM interfaces. ```rust let root = doc.DocumentElement()?; assert!(root.NodeName()? == "html"); println!("{}", root.InnerText()?); ``` -------------------------------- ### Create a Thread Pool Work Object Source: https://kennykerr.ca/rust-getting-started/calling-your-first-windows-api.html Use the CreateThreadpoolWork function to create a work object. This object represents a unit of work to be submitted to the thread pool. It requires a callback function. ```rust #![allow(unused)] fn main() { let work = CreateThreadpoolWork(Some(callback), None, None)?; } ``` -------------------------------- ### Wait for Thread Pool Callbacks to Complete Source: https://kennykerr.ca/rust-getting-started/calling-your-first-windows-api.html Employ WaitForThreadpoolWorkCallbacks to block execution until all submitted work items have finished. Setting the second parameter to 'false' ensures the wait is blocking. ```rust #![allow(unused)] fn main() { WaitForThreadpoolWorkCallbacks(work, false); } ``` -------------------------------- ### Submit Work to the Thread Pool Source: https://kennykerr.ca/rust-getting-started/calling-your-first-windows-api.html Use SubmitThreadpoolWork to add the created work object to the thread pool's queue. This function can be called multiple times to submit the same work repeatedly. ```rust #![allow(unused)] fn main() { for _ in 0..10 { SubmitThreadpoolWork(work); } } ``` -------------------------------- ### Internal create_validator Function Signature Source: https://kennykerr.ca/rust-getting-started/implement-win32-api.html The internal `create_validator` function mirrors the public API but uses Rust's `Result` type for more idiomatic error propagation. ```rust #![allow(unused)] fn main() { unsafe fn create_validator(schema: *const u8, schema_len: usize, handle: *mut usize) -> Result<()> { // ... Ok(()) } } ``` -------------------------------- ### Internal JSON Validation Logic Source: https://kennykerr.ca/rust-getting-started/implement-win32-api.html Performs the core JSON validation logic. It dereferences the schema handle, parses the input value, and validates it against the schema, optionally producing a sanitized output. ```rust unsafe fn validate( handle: usize, value: *const u8, value_len: usize, sanitized_value: *mut *mut u8, sanitized_value_len: *mut usize, ) -> Result<()> { // ... } ``` ```rust if handle == 0 { return Err(E_HANDLE.into()); } let schema = &*(handle as *const JSONSchema); ``` ```rust let value = json_from_raw_parts(value, value_len)?; ``` ```rust if schema.is_valid(&value) { if !sanitized_value.is_null() && !sanitized_value_len.is_null() { let value = value.to_string(); *sanitized_value = CoTaskMemAlloc(value.len()) as _; if (*sanitized_value).is_null() { return Err(E_OUTOFMEMORY.into()); } (*sanitized_value).copy_from(value.as_ptr(), value.len()); *sanitized_value_len = value.len(); } Ok(()) } else { // ... } ``` ```rust let mut message = String::new(); if let Some(error) = schema.validate(&value).unwrap_err().next() { message = error.to_string(); } ``` -------------------------------- ### Win32-style JSON Validator API Declarations Source: https://kennykerr.ca/rust-getting-started/implement-win32-api.html These are the C++ style declarations for the JSON validator API functions: CreateJsonValidator, ValidateJson, and CloseJsonValidator. ```c++ HRESULT __stdcall CreateJsonValidator(char const* schema, size_t schema_len, uintptr_t* handle); HRESULT __stdcall ValidateJson(uintptr_t handle, char const* value, size_t value_len, char** sanitized_value, size_t* sanitized_value_len); void __stdcall CloseJsonValidator(uintptr_t handle); ``` -------------------------------- ### Print Final Counter Value Source: https://kennykerr.ca/rust-getting-started/calling-your-first-windows-api.html Read and print the final value of the shared counter after all thread pool operations have completed. This demonstrates the result of the concurrent increments. ```rust #![allow(unused)] fn main() { let counter = COUNTER.read().unwrap(); println!("counter: {}", *counter); } ``` -------------------------------- ### Close JSON Validator Function Source: https://kennykerr.ca/rust-getting-started/implement-win32-api.html Frees the memory allocated for a compiled JSON schema validator. Accepts a handle (usize) and safely drops the boxed schema if the handle is non-zero. ```rust #![allow(unused)] fn main() { #[no_mangle] unsafe extern "system" fn CloseJsonValidator(handle: usize) { if handle != 0 { _ = Box::from_raw(handle as *mut JSONSchema); } } } ``` -------------------------------- ### Close the Thread Pool Work Object Source: https://kennykerr.ca/rust-getting-started/calling-your-first-windows-api.html Call CloseThreadpoolWork to release the resources associated with the work object after it's no longer needed. This prevents memory leaks. ```rust #![allow(unused)] fn main() { CloseThreadpoolWork(work); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.