clips.psm1

using namespace System.Reflection
using namespace System.Linq.Expressions
using namespace System.Runtime.InteropServices

$keys, $types = ($x = [PSObject].Assembly.GetType(
  'System.Management.Automation.TypeAccelerators'
))::Get.Keys, @{ ptr = [IntPtr] }
$types.Keys.ForEach{ if ($_ -notin $keys) { $x::Add($_, $types.$_) } }

function New-Delegate {
  [CmdletBinding()]
  param(
    [Parameter(Mandatory, Position=0)]
    [ValidateNotNullOrEmpty()]
    [String]$Module,

    [Parameter(Mandatory, Position=1)]
    [ValidateScript({![String]::IsNullOrEmpty($_)})]
    [ScriptBlock]$Signature
  )

  begin {
    $kernel32 = @{}
    [Array]::Find((
      Add-Type -AssemblyName Microsoft.Win32.SystemEvents -PassThru
    ), [Predicate[Type]]{$args[0].Name -eq 'kernel32'}
    ).GetMethods([BindingFlags]'NonPublic, Static, Public').Where{
      $_.Name -cmatch '\AGet(P|M)'
    }.ForEach{ $kernel32[$_.Name] = $_ }

    if ((
      $mod = $kernel32.GetModuleHandle.Invoke($null, @($Module))
    ) -eq [IntPtr]::Zero) {
      throw [DllNotFoundException]::new("Can not find $Module library.")
    }
  }
  process {}
  end {
    $funcs = @{}
    for ($i, $m, $fn, $p = 0, ([Expression].Assembly.GetType(
        'System.Linq.Expressions.Compiler.DelegateHelpers'
      ).GetMethod('MakeNewCustomDelegate', [BindingFlags]'NonPublic, Static')
      ), [Marshal].GetMethod('GetDelegateForFunctionPointer', ([IntPtr])),
      $Signature.Ast.FindAll({$args[0].CommandElements}, $true).ToArray();
      $i -lt $p.Length; $i++
    ) {
      $fnret, $fname = ($def = $p[$i].CommandElements).Value

      if ((
        $fnsig = $kernel32.GetProcAddress.Invoke($null, @($mod, $fname))
      ) -eq [IntPtr]::Zero) {
        throw [InvalidOperationException]::new("Can not find $fname signature.")
      }

      $fnargs = $def.Pipeline.Extent.Text
      [Object[]]$fnargs = ((
        ($fnargs -replace '\[|\]' -split ',\s+?') + $fnret
      ), $fnret)[[String]::IsNullOrEmpty($fnargs)]

      $funcs[$fname] = $fn.MakeGenericMethod(
        [Delegate]::CreateDelegate([Func[[Type[]], Type]], $m).Invoke($fnargs)
      ).Invoke([Marshal], $fnsig)
    }
    Set-Variable $Module -Value $funcs -Scope Script -Force
  }
}

function Get-Clipboard {
  [CmdletBinding()]param()

  begin {
    New-Delegate kernel32 {
      ptr GlobalLock([ptr])
      bool GlobalUnlock([ptr])
    }

    New-Delegate user32 {
      bool CloseClipboard
      uint EnumClipboardFormats([uint])
      ptr GetClipboardData([uint])
      bool OpenClipboard([ptr])
    }

    function private:Test-ClipFormat([UInt32]$Format) {
      process {
        while (0 -ne ($fmt = $user32.EnumClipboardFormats.Invoke($fmt))) {
          if ($fmt -eq $Format) { return $true }
        }
        return $false
      }
    }
  }
  process {}
  end {
    if ($user32.OpenClipboard.Invoke([IntPtr]::Zero)) {
      Write-Verbose 'clipboard has been successfully opened.'

      try {
        if (!(Test-ClipFormat 13)) {
          throw 'clipboard does not contain any textual data.'
        }

        if (($data = $user32.GetClipboardData.Invoke(13)) -eq [IntPtr]::Zero) {
          throw 'clipboard retrieval failed.'
        }

        if (($ptxt = $kernel32.GlobalLock.Invoke($data)) -eq [IntPtr]::Zero) {
          throw 'locking memory failed.'
        }

        [Marshal]::PtrToStringAuto($ptxt)
      }
      catch { Write-Verbose $_ }
      finally {
        if ($ptxt) {
          if (!$kernel32.GlobalUnlock.Invoke($data)){
            Write-Verbose 'unlocking memory failed.'
          }
        }
      }

      if ($user32.CloseClipboard.Invoke()) {
        Write-Verbose 'clipboard has has been successfully closed.'
      }
    } # success
  }
}

Export-ModuleMember -Function Get-Clipboard