Nowadays I am trying to implement something that includes lot of P/Invoke calls, and several DWORD flags are included in the calls. The DWORD is unsigned 32-bit integer and is usually represented like hexadecimal number – 0x000000ff. At first it all seemed peachy until it  turned out that the standard PowerShell converts the hexadecimal representation of number to integer (values less than 0 are possible) and not the unsigned integer (negative numbers are not possible). Let’s see an example:

Here is the maximum value of the DWORD represented in hexadecimal format 0xffffffff. I expect it to be 4294967295 (the same as the maximum value of unsigned 32-bit integer [uint32]::MaxValue) but running it in PowerShell console returns -1, a value clearly not belonging to scope of the UInt32 type.

I realized I need to do the conversion myself and found it can be done easily using static methods of the System.Convert class. In the example I specify a hexadecimal representation of the number as a string and the base of the hexadecimal number which is 16.

[Convert]::ToUInt32("0xffffffff",16)
Note: Changing the base value to 2 enables you to work with binary numbers, changing it to 8 enables you to work with octal number, changing it to 10 makes it work with decimal numbers (default).

This is easy, but inconvenient and error-prone so I created function called ConvertFrom-Dword that validates the input values for me and returns the number as unsigned integer:

function ConvertFrom-Dword
{
	[CmdletBinding()]
	param (
		[Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true)]
		[ValidatePattern("^(0x)?(0+)?[0-9|a-f]{1,8}`$")]
		[string]$Value
	)
	#0xffffffff -band 0xFFFFFFFFL is also possible
	$base = 16
	Write-Verbose "Converting DWORD value $value to decimal."
	[Convert]::ToUInt32($Value,$base)
}
ConvertFrom-Dword -Value 0xffffffff
(ConvertFrom-Dword -Value 0xffffffff).getType().fullname

4294967295
System.UInt32

This is easier but still not perfect, but for the time being it will do.

In real life we can for example take the CreateFile function documented here. By the name of the function you would probably say it is used just to create files, but it is also able to open existing file. When you perform this action you can decide if you need the file opened exclusively (lock it) or if you want to share access to the file with other processes. For that purpose there is parameter dwShareMode you can set by specifying correct “flags” (DWORD values).

The description on the linked page says:

The requested sharing mode of the file or device, which can be read, write, both, delete, all of these, or none (refer to the following table).

0
0×00000000

FILE_SHARE_DELETE
0×00000004

FILE_SHARE_READ
0×00000001

FILE_SHARE_WRITE
0×00000002

If you read carefully you probably wonder how you specify the “both” and “all of them” cases if there are no such items in the table. The solution is connecting them by the “-bor” (bit OR) operator.  If you want to share both write and read you do: 0×00000001 –bor 0×00000002. Which returns 3 or 0×00000003 in case you use this little trick.

function ConvertTo-Dword ([uint32]$Number)
{
	"0x{0:x8}" -f ($Number)
}
ConvertTo-Dword 3

0x00000003

The operation –bor did, may look like a simple adding but it is not because 1 –bor 1 = 1, instead it does operation on binary representation of the number. Look at the items in the table again. Why is 0×00000003 missing?

Now I see I need some more instruments to work easily with this type of data, back to console…