Encoding byte array for performUpkeep() in Chainlink Keepers - chainlink

We have this code below which will encode a uint256 array into a byte array.
For some reason, performUpkeep() will be successful in Remix IDE but not using Hardhat.
function checkUpkeep(bytes calldata checkData) external view override returns (bool, bytes memory) {
bool flag = false;
uint256 counter = 0;
uint256[] memory numbers = new uint256[](10);
for (uint256 i = 0; i < 10; i+=2) {
numbers[counter++] = i;
}
bytes memory checkData = abi.encode(numbers);
return (flag, checkData);
}
function performUpkeep(bytes calldata performData) external override {
uint256[] memory numbers = abi.decode(performData, (uint256[]));
console.log("The first number is:", numbers[0]);
}
The end goal here is to pass data through to performUpkeep succesfully.

The performUpkeep() function takes an argument of type bytes. It then decodes that argument into an array of uint256. Before passing data to performUpkeep() in Hardhat, you must encode the array of uint256 you wish to pass as an argument according to the standard EVM encoding format.
To do so in Hardhat (Javascript) you can use the ethers.js library to access the defaultAbiCoder object and encode your arguments using it. An example can be seen below
let abiCoder = ethers.utils.defaultAbiCoder;
let dataEncoded = abiCoder.encode([ "uint[]"], [[ 1, 2, 3]]);
await keeperContract.performUpkeep(dataEncoded)

Related

Requesting random number on Chainlink Testnet and getting zeroes

I have been working on something that encapsulates chainlink random number on nfts to provide them to users, using a chainlink subscription and adding my smart contract as a comsumer. When working on testnet I am finding some times it gives me zero numbers and not a random one. This behaviour is random. Subscription is funded and smart contract added as a comsumer.
May this happen on mainnet also?
On most cases this kind of errors are only testnet timeouts, or other stuff related to slower infrastructure.
I wish to implement something to prevent shipping the NFT when zeroes are recevied:
I tried to put assert(randomNumber!=[zero]); but I got some errors, as gas stimation functions on wallets can ensure this, so they set highest fee.
Any suggestions to keep this secured?
This is the main testnet smart contract bsc address https://testnet.bscscan.com/address/0x74623BaE2c3AcC39Db224c236229dc4d5aD1F64d#code
is there any warranty the request random number operation finishes succesfully, or how can I take care of it on my code?
I have posted chainlink related functions too, where I slice the numbers to get them one by one in the lottery.
Subscription is funded and smart contract added as a comsumer. geting some times zero numbers and not a random one
these are the two functions
function closeSaleGetWinner()
external
nonReentrant
onlyRole(OPERATOR_ROLE)
{
requestRandomWords();
require(
isDrawLive,
"There's not a live draw neither ticket sale is opened"
);
uint256[6] memory numberOfMatches;
uint256 drawPrice;
// set the total pool price to BUSD smart contract balance
drawPrice =
checkBUSDContractBalance() *
allDraws[currentDraw].poolPercentage; // use 1 * 10**18 for use the whole pool
// close ticket sale and get random winner number from s_randomWords
isDrawLive = false;
//assert(s_randomWords[0]!=0);
allDraws[currentDraw].winnerNumber = s_slicedRandomWords;
//unchecked {
uint256 j;
Ticket storage _ticket;
uint256 _match;
// check and update matched numbers per ticket on allTickets structure
for (uint256 i = 0; i < drawToTickets[currentDraw].length; i++) {
j = drawToTickets[currentDraw][i];
_ticket = allTickets[j];
_match = checkWinner(_ticket);
_ticket.matchedNumbers = _match;
numberOfMatches[_match] = numberOfMatches[_match] + 1;
}
// after storing number of winners with [_match] matches calculate win per group
// it's time to overwrite reward variable with
// 1st the part of the price from the total pool for #i number of matches
// 2nd divide e
for (uint256 i = 0; i < 5; i++) {
allDraws[currentDraw].reward[i] =
allDraws[currentDraw].reward[i] *
drawPrice;
if (numberOfMatches[i + 1] > 0) {
allDraws[currentDraw].reward[i] = SafeMath.div(
allDraws[currentDraw].reward[i],
numberOfMatches[i + 1]
);
} else {
allDraws[currentDraw].reward[i] = 0;
}
}
// once stored delete random generated number for further checks
delete (s_randomWords);
delete (s_slicedRandomWords);
}
/*
compares the ticket number with the winner number of the draw and returns a value
representing matched number between 0 to 5 (6 values)
*/
function checkWinner(Ticket storage t) internal view returns (uint256) {
uint256 _match = 0;
// we go and compare digit by digit storing number of consecutive matches and stopping when
// there are no more coincidences
uint256[5] memory ticketNumber = t.number;
uint256[5] memory winnerNumber = allDraws[_drawIdCounter.current() - 1]
.winnerNumber;
for (uint256 i = 0; i < 5; i++) {
// If there exists any distinct
// lastTicketDigit, then return No
if (ticketNumber[i] == winnerNumber[i]) {
_match = _match + 1;
} else return _match;
}
return _match;
}
function buyRandomTicket() public nonReentrant {
uint256[] storage myTickets = accounts[msg.sender].myTicketsHistory;
require(isDrawLive, "Sorry there's no live draw by now");
require(!Address.isContract(msg.sender), "only EOA allowed");
address user = address(msg.sender);
uint256 _value = allDraws[currentDraw].ticketPrice;
// check balance and user allowance
uint256 busdUserBalance = BUSD.balanceOf(msg.sender);
require(busdUserBalance >= _value, "Not enough balance");
uint256 allowance = BUSD.allowance(msg.sender, address(this));
require(allowance >= _value, "Check the BUSD allowance");
uint256 devsReward = _value.mul(5).div(100);
uint256 otherReward = _value.mul(20).div(100);
// get payment
BUSD.safeTransferFrom(msg.sender, address(this), _value);
requestRandomWords();
BUSD.safeTransfer(w1, devsReward);
BUSD.safeTransfer(w2, devsReward);
BUSD.safeTransfer(w3, otherReward);
/*pay referral*/
if (accounts[msg.sender].referrer != address(0))
payReferral(_value, address(msg.sender));
Ticket memory randomTicket = Ticket(
user,
currentDraw,
_ticketIdCounter.current(),
s_slicedRandomWords,
false,
0
);
//require(s_randomWords[0]!=0);
uint256[] storage drawTickets = drawToTickets[currentDraw];
// add to the mapping to store tickets sold for a draw
drawTickets.push(randomTicket.ticketID);
myTickets.push(randomTicket.ticketID);
allTickets.push(randomTicket);
safeMint(user);
// set to 0 random storage variable for further checks
delete (s_randomWords);
delete (s_slicedRandomWords);
}
/* CHAINLINK FUNCTIONS */
// Assumes the subscription is funded sufficiently.
function requestRandomWords() internal {
// Will revert if subscription is not set and funded.
s_requestId = COORDINATOR.requestRandomWords(
keyHash,
s_subscriptionId,
requestConfirmations,
callbackGasLimit,
numWords
);
}
function fulfillRandomWords(
uint256, /* requestId */
uint256[] memory randomWords
) internal override {
uint256 _lastDigit;
s_randomWords = randomWords;
uint256 aux = randomWords[0];
for (uint256 i = 0; i < 5; i++) {
_lastDigit = aux % 10;
s_slicedRandomWords[i] = _lastDigit;
aux = aux / 10;
}
}
```

How do I retrieve a string from a PWSTR after a Win32 function succeeds?

I would like to get my username in an std::String using the windows-rs crate.
use bindings::Windows::Win32::{
System::WindowsProgramming::GetUserNameW,
Foundation::PWSTR,
};
fn main() {
let mut pcbbuffer: u32 = 255;
let mut helper: u16 = 0;
let lpbuffer = PWSTR(&mut helper);
println!("lpbuffer: {:?}\npcbbuffer: {:?}", lpbuffer, pcbbuffer);
unsafe {
let success = GetUserNameW(lpbuffer, &mut pcbbuffer);
println!("GetUserNameW succeeded: {:?}\nlpbuffer: {:?}\npcbbuffer: {:?}", success.as_bool(), lpbuffer, pcbbuffer);
}
}
produces the output:
lpbuffer: PWSTR(0xca20f5f76e)
pcbbuffer: 255
GetUserNameW succeeded: true
lpbuffer: PWSTR(0x7200650073)
pcbbuffer: 5
The username is "user" that's 4 + 1 terminating character = 5 which is good. I also see the GetUserNameW function succeeded and the pointer to the string changed.
What are the next steps?
The code as posted works by coincidence alone. It sports a spectacular buffer overflow, hardly what you'd want to see in Rust code. Specifically, you're taking the address of a single u16 value, and pass it into an API, telling it that the pointed-to memory were 255 elements in size.
That needs to be solved: You will have to allocate a buffer large enough to hold the API's output first.
Converting a UTF-16 encoded string to a Rust String with its native encoding can be done using several different ways, such as String::from_utf16_lossy().
The following code roughly sketches out the approach:
fn main() {
let mut cb_buffer = 257_u32;
// Create a buffer of the required size
let mut buffer = Vec::<u16>::with_capacity(cb_buffer as usize);
// Construct a `PWSTR` by taking the address to the first element in the buffer
let lp_buffer = PWSTR(buffer.as_mut_ptr());
let result = unsafe { GetUserNameW(lp_buffer, &mut cb_buffer) };
// If the API returned success, and more than 0 characters were written
if result.as_bool() && cb_buffer > 0 {
// Construct a slice over the valid data
let buffer = unsafe { slice::from_raw_parts(lp_buffer.0, cb_buffer as usize - 1) };
// And convert from UTF-16 to Rust's native encoding
let user_name = String::from_utf16_lossy(buffer);
println!("User name: {}", user_name);
}
}

How do I decrypt data encrypted by Ruby's `symmetric-encryption` gem in another language?

I want to access data in a database created by Rails for use by non-Ruby code. Some fields use attr_encrypted accessors, and the library in use is the symmetric-encryption gem. I consistently get a "wrong final block length" error if I try to decrypt the data with, e.g., the NodeJS crypto library.
I suspect this has to do either with character encoding or with padding, but I can't figure it out based on the docs.
As an experiment, I tried decrypting data from symmetric-encryption in Ruby's own OpenSSL library, and I get either a "bad decrypt" error or the same problem:
SymmetricEncryption.cipher = SymmetricEncryption::Cipher.new(
key: "1234567890ABCDEF",
iv: "1234567890ABCDEF",
cipher_name: "aes-128-cbc"
)
ciphertext = SymmetricEncryption.encrypt("Hello world")
c = OpenSSL::Cipher.new("aes-128-cbc")
c.iv = c.key = "1234567890ABCDEF"
c.update(ciphertext) + c.final
That gives me a "bad decrypt" error.
Interestingly, the encrypted data in the database can be decrypted by the symmetric-encryption gem, but isn't the same as the output of SymmetricEncryption.encrypt (and OpenSSL doesn't successfully decrypt it, either).
Edit:
psql=# SELECT "encrypted_firstName" FROM people LIMIT 1;
encrypted_firstName
----------------------------------------------------------
QEVuQwBAEAAuR5vRj/iFbaEsXKtpjubrWgyEhK5Pji2EWPDPoT4CyQ==
(1 row)
Then
irb> SymmetricEncryption.decrypt "QEVuQwBAEAAuR5vRj/iFbaEsXKtpjubrWgyEhK5Pji2EWPDPoT4CyQ=="
=> "Lurline"
irb> SymmetricEncryption.encrypt "Lurline"
=> "QEVuQwAAlRBeYptjK0Fg76jFQkjLtA=="
Looking at the source for the symmetric-encryption gem, by default it adds a header to the output and base64 encodes it, although both of these are configurable.
To decrypt using Ruby’s OpenSSL directly, you will need to decode it and strip off this header, which is 6 bytes long in this simple case:
ciphertext = Base64.decode64(ciphertext)
ciphertext = ciphertext[6..-1]
c = OpenSSL::Cipher.new("aes-128-cbc")
c.decrypt
c.iv = "1234567890ABCDEF"
c.key = "1234567890ABCDEF"
result = c.update(ciphertext) + c.final
Of course, you may need to alter this depending on what settings you are using in symmetric-encryption, e.g. the header length may vary. In order to decrypt the result from the database you will need to parse the header. Have a look at the source.
Based on the Rust implementation done by #Shepmaster in my other question (and the source code for the symmetric-encryption gem), I have a working version in TypeScript. #matt is close with his answer, but the header can actually have additional bytes containing metadata about the encrypted data. Note that this doesn't handle (1) compressed encrypted data, or (2) setting the encryption algorithm from the header itself; neither situation is relevant to my use case.
import { createDecipher, createDecipheriv, Decipher } from "crypto";
// We use two types of encoding with SymmetricEncryption: Base64 and UTF-8. We
// define them in an `enum` for type safety.
const enum Encoding {
Base64 = "base64",
Utf8 = "utf8",
}
// Symmetric encryption's header contains the following data:
interface IHeader {
version: number, // The version of the encryption algo
isCompressed: boolean, // Whether the data is compressed (TODO: Implement)
hasIv: boolean, // Whether the header itself has the IV
hasKey: boolean, // Whether the header itself has the Key
hasCipherName: boolean, // Whether the header contains the cipher name
hasAuthTag: boolean, // Whether the header has an authorization tag
offset: number, // How many bytes into the encoded ciphertext the actual encrypted data starts
iv?: Buffer, // The IV, present only if `hasIv` is true
key?: Buffer, // The key, present only if `hasKey` is true
// The cipher name, present only if `hasCipherName` is true. Currently ignored.
cipherName?: string,
authTag?: string, // The authorization tag, present only if // `hasAuthTag` is true
}
// Byte 6 of the header contain bit flags
interface IFlags {
isCompressed: boolean,
hasIv: boolean,
hasKey: boolean,
hasCipherName: boolean,
hasAuthTag: boolean
}
// The 7th byte until the end of the header have the actual values. If all
// of the flags are false, the header ends at the 6th byte.
interface IValues {
iv?: Buffer,
key?: Buffer,
cipherName?: string,
authTag?: string,
size: number,
}
/**
* Represent the encoded ciphertext, complete with the SymmetricEncryption header.
*/
class Ciphertext {
// Bit flags corresponding to the data encoded in byte 6 of the
// header.
readonly FLAG_COMPRESSED = 0b1000_0000;
readonly FLAG_IV = 0b0100_0000;
readonly FLAG_KEY = 0b0010_0000;
readonly FLAG_CIPHER_NAME = 0b0001_0000;
readonly FLAG_AUTH_TAG = 0b0000_1000;
// The literal data encoded in bytes 1 - 4 of the header
readonly MAGIC_HEADER = "#EnC";
// If any of the values represented by the bit flags is present, the first 2
// bytes of the data tells us how long the actual value is. In other words,
// the first 2 bytes aren't the value itself, but rather give the info about
// the length of the rest of the value.
readonly LENGTH_INFO_SIZE = 2;
public header: IHeader | null;
public data: Buffer;
private cipherBuffer: Buffer;
constructor(private input: string) {
this.cipherBuffer = new Buffer(input, Encoding.Base64);
this.header = this.getHeader();
const offset = this.header ? this.header.offset : 0; // If no header, then no offset
this.data = this.cipherBuffer.slice(offset);
}
/**
* Extract the header from the data
*/
private getHeader(): IHeader | null {
let offset = 0;
// Bytes 1 - 4 are the literal `#EnC`. If that's absent, there's no
// SymmetricEncryption header.
if (this.cipherBuffer.toString(Encoding.Utf8, offset, offset += 4) != this.MAGIC_HEADER) {
return null;
}
// Byte 5 is the version
const version = this.cipherBuffer.readInt8(offset++); // Post increment
// Byte 6 is the flags
const rawFlags = this.cipherBuffer.readInt8(offset++);
const flags = this.readFlags(rawFlags);
// Bytes 7 - end are the values.
const values = this.getValues(offset, flags);
offset += values.size;
return Object.assign({ version, offset }, flags, values);
}
/**
* Get the values for `iv`, `key`, `cipherName`, and `authTag`, if any are
* set, based on the bitflags. Return that data, plus how many bytes in the
* header those values represent.
*
* #param offset - What byte we're on when we get to the values. Should be 7
* #param flags - The flags we've extracted, showing us which values to expect
*/
private getValues(offset: number, flags: IFlags): IValues {
let iv: Buffer | undefined = undefined;
let key: Buffer | undefined = undefined;
let cipherName: string | undefined = undefined;
let authTag: string | undefined = undefined;
let size = 0; // If all of the bit flags are false, there is no additional data.
// For each value, see if the flag is set to true. If it is, we need to
// read the value. Keys and IVs need to be `Buffer` types; other values
// should be strings.
[iv, size] = flags.hasIv ? this.readBuffer(offset) : [undefined, size];
[key, size] = flags.hasKey ? this.readBuffer(offset + size) : [undefined, size];
[cipherName, size] = flags.hasCipherName ? this.readString(offset + size) : [undefined, size];
[authTag, size] = flags.hasAuthTag ? this.readString(offset + size) : [undefined, size];
return { iv, key, cipherName, authTag, size };
}
/**
* Parse the 16-bit integer representing the bit flags into an object for
* easier handling
*
* #param flags - The 16-bit integer that contains the bit flags
*/
private readFlags(flags: number): IFlags {
return {
isCompressed: (flags & this.FLAG_COMPRESSED) != 0,
hasIv: (flags & this.FLAG_IV) != 0,
hasKey: (flags & this.FLAG_KEY) != 0,
hasCipherName: (flags & this.FLAG_CIPHER_NAME) != 0,
hasAuthTag: (flags & this.FLAG_AUTH_TAG) != 0
}
}
/**
* Read a string out of the value at the specified offset. Return the value
* itself, plus the number of bytes consumed by the value (including the
* 2-byte encoding of the length of the actual value).
*
* #param offset - The offset (bytes from the beginning of the encoded,
* encrypted Buffer) at which the value in question begins
*/
private readString(offset: number): [string, number] {
// The length is the first 2 bytes, encoded as a little-endian 16-bit integer
const length = this.cipherBuffer.readInt16LE(offset);
// The total size occupied in the header is the 2 bytes encoding length plus the length itself
const size = this.LENGTH_INFO_SIZE + length;
const value = this.cipherBuffer.toString(Encoding.Base64, offset + this.LENGTH_INFO_SIZE, offset + size);
return [value, size];
}
/**
* Read a Buffer out of the value at the specified offset. Return the value
* itself, plus the number of bytes consumed by the value (including the
* 2-byte encoding of the length of the actual value).
*
* #param offset - The offset (bytes from the beginning of the encoded,
* encrypted Buffer) at which the value in question begins
*/
private readBuffer(offset: number): [Buffer, number] {
// The length is the first 2 bytes, encoded as a little-endian 16-bit integer
const length = this.cipherBuffer.readInt16LE(offset);
// The total size occupied in the header is the 2 bytes encoding length plus the length itself
const size = this.LENGTH_INFO_SIZE + length;
const value = this.cipherBuffer.slice(offset + this.LENGTH_INFO_SIZE, offset + size);
return [value, size];
}
}
/**
* Allow decryption of data encrypted by Ruby's `symmetric-encryption` gem
*/
class SymmetricEncryption {
private key: Buffer;
private iv?: Buffer;
constructor(key: string, private algo: string, iv?: string) {
this.key = new Buffer(key);
this.iv = iv ? new Buffer(iv) : undefined;
}
public decrypt(input: string): string {
const ciphertext = new Ciphertext(input);
// IV can be specified by the user. But if it's encoded in the header
// itself, go with that instead.
const iv = (ciphertext.header && ciphertext.header.iv) ? ciphertext.header.iv : this.iv;
// Key can be specified by the user. but if it's encoded in the header,
// go with that instead.
const key = (ciphertext.header && ciphertext.header.key) ? ciphertext.header.key : this.key;
const decipher: Decipher = iv ?
createDecipheriv(this.algo, key, iv) :
createDecipher(this.algo, key);
// Terse version of `update()` + `final()` that passes type checking
return Buffer.concat([decipher.update(ciphertext.data), decipher.final()]).toString();
}
}
const s = new SymmetricEncryption("1234567890ABCDEF", "aes-128-cbc", "1234567890ABCDEF");
console.log(s.decrypt("QEVuQwAADWK0cKzgFIovdIThq9Scrg==")); // => "Hello world"

Calling the GetUserName WinAPI function with a mutable string doesn't populate the string

This appears to partially work but I cannot get the string value to print
pub fn test() {
let mut buf: Vec<u16> = vec![0; 64];
let mut sz: DWORD = 0;
unsafe {
advapi32::GetUserNameW(buf.as_mut_ptr(), &mut sz);
}
let str1 = OsString::from_wide(&buf).into_string().unwrap();
println!("Here: {} {}", sz, str1);
}
Prints:
Here: 10
When I expect it to also print
Here: 10 <username>
As a test, the C version
TCHAR buf[100];
DWORD sz;
GetUserName(buf, &sz);
seems to populate buf fine.
GetUserName
You should re-read the API documentation for GetUserName to recall how the arguments work:
lpnSize [in, out]
On input, this variable specifies the size of the
lpBuffer buffer, in TCHARs. On output, the variable receives the
number of TCHARs copied to the buffer, including the terminating null
character. If lpBuffer is too small, the function fails and
GetLastError returns ERROR_INSUFFICIENT_BUFFER. This parameter
receives the required buffer size, including the terminating null
character.
TL;DR:
On input: caller tells the API how many spaces the buffer has.
On success: API tells the caller how many spaces were used.
On failure: API tells the caller how many spaces were needed.
C version
This has a fixed-size stack-allocated array of 100 TCHARs.
This code is broken and unsafe because sz is uninitialized. This allows the API to write an undefined number of characters to a buffer that's only 100 long. If the username is over 100 characters, you've just introduced a security hole into your program.
Rust version
The Rust code is broken in a much better way. sz is set to zero, which means "you may write zero entries of data", so it writes zero entries. Thus, the Vec buffer is full of zeros and the resulting string is empty. The buffer is reported too small to receive the username, so GetUserNameW sets sz to the number of characters that the buffer needs to have allocated.
What to do
One "fix" would be to set sz to the length of your array. However, this is likely to have over- or under-allocated the buffer.
If you are ok with a truncated string (and I'm not sure if TCHAR strings can be split arbitrarily, I know UTF-8 cannot), then it would be better to use a fixed-size array like the C code.
If you want to more appropriately allocate memory to call this type of WinAPI function, see What is the right way to allocate data to pass to an FFI call?.
extern crate advapi32;
extern crate winapi;
use std::ptr;
fn get_user_name() -> String {
unsafe {
let mut size = 0;
let retval = advapi32::GetUserNameW(ptr::null_mut(), &mut size);
assert_eq!(retval, 0, "Should have failed");
let mut username = Vec::with_capacity(size as usize);
let retval = advapi32::GetUserNameW(username.as_mut_ptr(), &mut size);
assert_ne!(retval, 0, "Perform better error handling");
assert!((size as usize) <= username.capacity());
username.set_len(size as usize);
// Beware: This leaves the trailing NUL character in the final string,
// you may want to remove it!
String::from_utf16(&username).unwrap()
}
}
fn main() {
println!("{:?}", get_user_name()); // "IEUser\u{0}"
}

Build routines for 1Byte/2Byte access based on SetPhysLong() in WinIo v3.0

I have one question about how to build routines for 1Byte/2Byte access based on SetPhysLong() in WinIo v3.0.
SetPhysLong() is used to access memory in unit of DWORD(32bit) and my objective is to build my own routines:
SetPhysBYTE() to access memory in unit of BYTE(8bit unsigned), and
SetPhysWORD() to access memory in unit of WORD(16bit unsigned)
Someone told me below way can solve this problem:
Use GetPhysLong to retrieve the current DWORD contents
Put the new BYTE / WORD into the correct part of the DWORD
Then use SetPhysLong to write that back
But I think above way failed if below situation occurs:
Assume 4-byte register is mapped to memory 0x12345678 (because it is memory-mapped IO)
Assume 2nd byte of that register is the Status register and the attribute is "Write 1 to clear" and 2nd byte is 0x40 now
Assume we want to write 0xA5 to memory 0x12345678. Follow your way and we got:
use GetPhysLong then returns 0x00004000
put 0xA5 to LSB and we got 0x000040A5
use SetPhysLong to set 0x000040A5 to memory address 0x12345678
This is NOT correct because value 0x40 will be written to 2nd byte and clear it to 0x00 !!!
Thus my objective is to use SetPhysBYTE(0x12345678, 0xA5) to achieve my goal and do not influence other bytes based on below SetPhysLong()....
bool _stdcall SetPhysLong(PBYTE pbPhysAddr, DWORD dwPhysVal)
{
PDWORD pdwLinAddr;
tagPhysStruct PhysStruct;
if (!IsWinIoInitialized)
return false;
if (g_Is64BitOS)
{
PhysStruct.pvPhysAddress = (DWORD64)pbPhysAddr;
}
else
{
// Avoid sign extension issues
PhysStruct.pvPhysAddress = (DWORD64)(DWORD32)pbPhysAddr;
}
PhysStruct.dwPhysMemSizeInBytes = 4;
pdwLinAddr = (PDWORD)MapPhysToLin(PhysStruct);
if (pdwLinAddr == NULL)
return false;
*pdwLinAddr = dwPhysVal;
UnmapPhysicalMemory(PhysStruct);
return true;
}
[EDIT] I have solved this and please reference below code if need be...
bool _stdcall SetPhysBYTE(PBYTE pbPhysAddr, BYTE bPhysVal)
{
PDWORD pdwLinAddr;
tagPhysStruct PhysStruct;
if (!IsWinIoInitialized)
return false;
if (g_Is64BitOS)
{
PhysStruct.pvPhysAddress = (DWORD64)pbPhysAddr;
}
else
{
// Avoid sign extension issues
PhysStruct.pvPhysAddress = (DWORD64)(DWORD32)pbPhysAddr;
}
PhysStruct.dwPhysMemSizeInBytes = 1;
pdwLinAddr = (PDWORD)MapPhysToLin(PhysStruct);
if (pdwLinAddr == NULL)
return false;
*(((PBYTE)((DWORD)pdwLinAddr))) = bPhysVal;
UnmapPhysicalMemory(PhysStruct);
return true;
}
bool _stdcall SetPhysWORD(PBYTE pbPhysAddr, WORD wPhysVal)
{
PDWORD pdwLinAddr;
tagPhysStruct PhysStruct;
if (!IsWinIoInitialized)
return false;
if (g_Is64BitOS)
{
PhysStruct.pvPhysAddress = (DWORD64)pbPhysAddr;
}
else
{
// Avoid sign extension issues
PhysStruct.pvPhysAddress = (DWORD64)(DWORD32)pbPhysAddr;
}
PhysStruct.dwPhysMemSizeInBytes = 2;
pdwLinAddr = (PDWORD)MapPhysToLin(PhysStruct);
if (pdwLinAddr == NULL)
return false;
*(((PWORD)((DWORD)pdwLinAddr))) = wPhysVal;
UnmapPhysicalMemory(PhysStruct);
return true;
}
See the [EDIT] part of this question !

Resources