Help with (undocumeted) WinApi function

This topic contains 2 replies, has 3 voices, and was last updated by Profile photo of Max Kozlov Max Kozlov 1 month, 2 weeks ago.

  • Author
    Posts
  • #63739
    Profile photo of Paul Kerning
    Paul Kerning
    Participant

    Dear all,
    I have a AutoIt script which uses a undocumented gdi32 function (GetFontResourceInfoW) (Autoit: _WinAPI_GetFontResourceInfo).
    It returns the name of a font file (.fon, .ttf, .ttc, etc. installed or not)
    The script works perfect. I want to recode it now in Powershell.
    The function prototype (from GetFontResourceInfo) is like:

       BOOL GetFontResourceInfo(
       LPCTSTR lpszFilename,    // font file name
       LPDWORD cbBuffer,        // size of buffer for resouce information
       LPVOID lpBuffer,         // buffer for returned resouce information
       DWORD dwQueryType,       / resouce information query type
    );
    

    My first try in Powershell, but it does not return the font name :

    $code=@'
    	using System;
    	using System.Collections.Generic;
    	using System.Text;
    	using System.IO;
    	using System.Runtime.InteropServices;
    
    	public static class  FontUtil{
    
            [DllImport("gdi32.dll")] 
                public static extern bool GetFontResourceInfoW(string lpszFilename, ref UInt32 cbBuffer, out IntPtr lpBuffer, UInt32 dwQueryType); 
    	}
    '@
    Add-Type $code
    
    [string]$fn = 'c:\windows\fonts\arial.ttf'
    [Uint32]$b = 260
    [IntPtr]$LocalStructPtr = [Runtime.InteropServices.Marshal]::AllocHGlobal(260)
    $ret=[fontutil]::GetFontResourceInfoW($fn, [ref] $b, [ref] $LocalStructPtr,[UInt32]1)
    [Runtime.InteropServices.Marshal]::PtrToStringAuto($LocalStructPtr,$b)
    [Runtime.InteropServices.Marshal]::FreeHGlobal($LocalStructPtr)
    

    Pleases help me!

  • #63749
    Profile photo of Don Jones
    Don Jones
    Keymaster

    Yeah, I think you might have more luck on StackOverflow – this is pretty beyond "PowerShell" in terms of what I'm able to help with, at least. This is a lot of layers you're going through, and I've never gotten these kinds of API calls to work well in PowerShell.

  • #63809
    Profile photo of Max Kozlov
    Max Kozlov
    Participant

    this slightly modified code works for me

    $code=@'
    	using System;
    	using System.Collections.Generic;
    	using System.Text;
    	using System.IO;
    	using System.Runtime.InteropServices;
    
    	public static class  FontUtil{
    
            [DllImport("gdi32.dll")] 
            public static extern bool GetFontResourceInfoW( [MarshalAs(UnmanagedType.LPTStr)]string lpszFilename, out UInt32 cbBuffer, IntPtr lpBuffer, UInt32 dwQueryType);
    
    		[DllImport("kernel32")]
    		public extern static int GetLastError();
    
    		public static string GetLastErrorMessage() {
    		   return (new System.ComponentModel.Win32Exception(System.Runtime.InteropServices.Marshal.GetLastWin32Error())).Message;
            }
    
    	}
    '@
    Add-Type $code
    
    [string]$fn = 'C:\Windows\Fonts\Arial.ttf'
    [Uint32]$b = 0
    $ret = [fontutil]::GetFontResourceInfoW($fn, [ref]$b, [IntPtr]::Zero, [UInt32]1) # return font name length in bytes
    if ($ret) {
      $b
      [IntPtr]$LocalStructPtr = [Runtime.InteropServices.Marshal]::AllocHGlobal($b)
      $ret=[FontUtil]::GetFontResourceInfoW($fn, [ref] $b, $LocalStructPtr,[UInt32]1)
      $s = [Runtime.InteropServices.Marshal]::PtrToStringAuto($LocalStructPtr) # ,$b / 2 - unicode is 2 bytes length
      [Runtime.InteropServices.Marshal]::FreeHGlobal($LocalStructPtr)
      $s
    }
    else {
      [FontUtil]::GetLastError(), [FontUtil]::GetLastErrorMessage()
    }
    

You must be logged in to reply to this topic.