build/google-cloud-sap-agent-diskmapping.ps1 (132 lines of code) (raw):
<#
.SYNOPSIS
Agent for SAP physical disk mapping script.
.DESCRIPTION
This powershell script is used to map Google Cloud disk names to Windows
physical disk names. 'Google mydisk' -> '\\.\PHYSICALDISKX'
#>
param (
[parameter(Mandatory=$true)]
[string] $diskName
)
$PhysicalDisksClass = @"
using System;
using Microsoft.Win32.SafeHandles;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
public class PhysicalDisks {
private const int PropertyStandardQuery = 0;
private const int StorageDeviceIdProperty = 2;
private const int ERROR_INSUFFICIENT_BUFFER = 122;
private const int StorageIdTypeVendorId = 1;
private const uint IOCTL_STORAGE_QUERY_PROPERTY = 0x2d1400;
[StructLayout(LayoutKind.Sequential)]
public struct StoragePropertyQuery {
public uint PropertyId;
public uint QueryType;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public byte[] AdditionalParameters;
}
[DllImport("kernel32.dll", SetLastError = true)]
private static extern SafeFileHandle CreateFile(
string lpFileName,
[MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess,
[MarshalAs(UnmanagedType.U4)] FileShare dwShareMode,
IntPtr lpSecurityAttributes,
[MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition,
[MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DeviceIoControl(
SafeFileHandle hDevice,
uint IoControlCode,
ref StoragePropertyQuery inBuffer,
int nInBufferSize,
IntPtr outBuffer,
int nOutBufferSize,
ref uint pBytesReturned,
IntPtr Overlapped
);
[StructLayout(LayoutKind.Sequential)]
public struct StorageIdentifier {
public int CodeSet;
public int Type;
public ushort IdentifierSize;
public ushort NextOffset;
public int Association;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public byte[] Identifier;
}
[StructLayout(LayoutKind.Sequential)]
public struct StorageDeviceIdDescriptor {
public uint Version;
public uint Size;
public uint NumberOfIdentifiers;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public byte[] Identifiers;
}
public static string queryPage83(string disk) {
disk = @"\\.\" + disk;
SafeFileHandle hDisk = CreateFile(disk, FileAccess.Read | FileAccess.Write, FileShare.Read | FileShare.Write, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
if (hDisk == null || hDisk.IsInvalid) {
return "";
}
StoragePropertyQuery spq = new StoragePropertyQuery();
spq.PropertyId = StorageDeviceIdProperty;
spq.QueryType = PropertyStandardQuery;
int buflen = 8192;
IntPtr bufptr = IntPtr.Zero;
uint bytesReturned = new uint();
do {
bufptr = Marshal.AllocHGlobal(buflen);
bool result = DeviceIoControl(hDisk, IOCTL_STORAGE_QUERY_PROPERTY, ref spq, Marshal.SizeOf(spq), bufptr, buflen, ref bytesReturned, IntPtr.Zero);
if (!result) {
int error = Marshal.GetLastWin32Error();
if (error == ERROR_INSUFFICIENT_BUFFER) {
Marshal.FreeHGlobal(bufptr);
bufptr = IntPtr.Zero;
buflen *= 2;
continue;
}
hDisk.Close();
return "";
}
break;
} while(true);
hDisk.Close();
IntPtr ptr = IntPtr.Add(bufptr, (int) Marshal.OffsetOf(typeof(StorageDeviceIdDescriptor), "NumberOfIdentifiers"));
uint n = (uint) Marshal.ReadInt32(ptr);
ptr = IntPtr.Add(bufptr, (int) Marshal.OffsetOf(typeof(StorageDeviceIdDescriptor), "Identifiers"));
for (uint i = 0; i < n; i++) {
int idType = Marshal.ReadInt32(IntPtr.Add(ptr, (int) Marshal.OffsetOf(typeof(StorageIdentifier), "Type")));
if (idType == StorageIdTypeVendorId) {
string id = Marshal.PtrToStringAnsi(IntPtr.Add(ptr, (int) Marshal.OffsetOf(typeof(StorageIdentifier), "Identifier")));
Marshal.FreeHGlobal(bufptr);
return id;
}
ptr = ptr + Marshal.ReadInt16(IntPtr.Add(ptr, (int) Marshal.OffsetOf(typeof(StorageIdentifier), "NextOffset")));
}
Marshal.FreeHGlobal(bufptr);
return "";
}
}
"@
# Compile and register C# PhysicalDisks class
Add-Type -TypeDefinition $PhysicalDisksClass -ErrorAction Stop
function Get-PhysicalDiskMapping {
param (
[string]$diskName
)
[Array] $physicalDisks = @(Get-PhysicalDisk)
for ($i = 0; $i -lt $physicalDisks.length; $i++) {
$drive = 'PhysicalDrive' + $physicalDisks[$i].DeviceId
$id = [PhysicalDisks]::queryPage83($drive)
if ($id -eq $diskName) {
return 'PhysicalDrive' + $physicalDisks[$i].DeviceId
}
}
return ''
}
Write-Host $(Get-PhysicalDiskMapping ('Google ' + $diskName))