Listing 2: Functions for graphic file import using installed 32-bit Type 2 filters

/* disable unnecessary level-4 warnings */
#pragma warning(disable: 4201)    // nonstandard extension used
#pragma warning(disable: 4514)    // unreferenced inline function

/* include files */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
#include "Filter.h"

/* private manifest constants */
#define FILTER_VER_TYPE2     2    // type 2 filter version

#define FILTER_FAILED        0    // operation failed
#define FILTER_TEXT          1    // filter is a text filter
#define FILTER_GRAPHIC       2    // filter is a graphic filter

#define CCH_MAX_KEY_NAME     256
#define CCH_MAX_FILTER_EXT   MAX_PATH

/* private constants */
static const LPCSTR lpszGetFilterInfoExportNames[] = { 
  "GetFilterInfo", 
  "GetFilterInfo@16", 
  "GETFILTERINFO", 
  NULL };

static const LPCSTR lpszGetFilterPrefExportNames[] = {
  "GetFilterPref", 
  "GetFilterPref@16", 
  "GETFILTERPREF", 
  NULL };

static const LPCSTR lpszImportGRExportNames[] = { 
  "ImportGR", 
  "ImportGr", 
  "ImportGR@16", 
  "ImportGr@16", 
  "IMPORTGR", 
  NULL };

/* private type defintions */
#pragma pack(push, 1)
typedef DWORD FILETYPE;
typedef struct
{
  WORD     slippery : 1;       // TRUE if file may disappear
  WORD     write    : 1;       // TRUE if open for write
  WORD     unnamed  : 1;       // TRUE if unnamed
  WORD     linked   : 1;       // Linked to an FS FCB
  WORD     mark     : 1;       // Generic mark bit
  FILETYPE fType;              // The file type
  WORD     handle;             // MS-DOS open file handle
  char     fullName[MAX_PATH]; // Device, path, file name
  DWORD    filePos;            // Current file posn
} FILESPEC;
#pragma pack(pop)

typedef UINT (CALLBACK * GETFILTERINFOPROC)(
  DWORD     idVersion, 
  LPSTR     lpszIni, 
  HGLOBAL * lphPrefMem, 
  HANDLE *  lphFileTypes);

typedef VOID (CALLBACK * GETFILTERPREFPROC)(
  HINSTANCE hInstance,
  HWND      hwndParent,
  HGLOBAL   hPrefMem,
  DWORD     dwFlags);

typedef UINT (CALLBACK * IMPORTGRPROC)(
  HDC        hdcPrint, 
  FILESPEC * lpfs,
  PICTINFO * lppi,
  HGLOBAL    hPrefMem);

/* private helper macros */
#ifndef CountOf
#define CountOf(array) (sizeof(array)/sizeof((array)[0]))
#endif

/* private function prototypes */
static BOOL FindGraphicImportFilter(
  LPCSTR     lpszExtension, 
  LPSTR      lpszDestFilterPath, 
  const UINT cchDestFilterPath);

static FARPROC ResolveProcAddress(
  const HMODULE  hLibrary, 
  const LPCSTR * lpszNames);



/***                       ***
 *** PUBLIC IMPLEMENTATION ***
 ***                       ***/

//---------------------------------------------------------------
//ImportGraphic
//---------------------------------------------------------------
UINT ImportGraphic(
  const LPCSTR lpszFileName,
  PICTINFO *   pPictInfo,
  const BOOL   fPreferences,
  const HWND   hwndParent)
{
  /* TEMPORARY variables */
  GETFILTERINFOPROC GetFilterInfo = NULL;
  GETFILTERPREFPROC GetFilterPref = NULL;
  IMPORTGRPROC      ImportGR = NULL;
  FILESPEC          fs = { 0 };
  HMODULE           hFilterLib = NULL;
  HGLOBAL           hPrefMem = NULL;
  char              szType[_MAX_EXT+1] = "";
  char              szImportFilter[MAX_PATH+1] = "";
  UINT              uResult = IE_NOT_MY_FILE;

  /* init */
  if (pPictInfo != NULL)
  {
    ZeroMemory(pPictInfo, sizeof(PICTINFO));
    /* get file type (extension) */
    _splitpath(lpszFileName, NULL, NULL, NULL, szType);
    if (szType[0] != NULL)
    {
      /* locate graphic import filter based on type */
      if (FindGraphicImportFilter(
        szType, 
        szImportFilter, 
        CountOf(szImportFilter)))
      {
        /* convert the file name to its short representation */
        if (!GetShortPathName(
          lpszFileName, 
          fs.fullName, 
          CountOf(fs.fullName)))
        {
          /* couldn't convert (probably UNC), use name anyway */
          lstrcpyn(fs.fullName, lpszFileName, 
            CountOf(fs.fullName));
        }
        /* load the filter library and locate the entry-points */
        hFilterLib = LoadLibrary(szImportFilter);
        if (hFilterLib != NULL)
        {
          GetFilterInfo = (GETFILTERINFOPROC)ResolveProcAddress(
            hFilterLib, 
            lpszGetFilterInfoExportNames);
          GetFilterPref = (GETFILTERPREFPROC)ResolveProcAddress(
            hFilterLib,
            lpszGetFilterPrefExportNames);
          ImportGR      = (IMPORTGRPROC)ResolveProcAddress(
            hFilterLib, 
            lpszImportGRExportNames);
          if ((GetFilterInfo!=NULL) && (ImportGR!=NULL))
          {
            /* get filter info */
            if (GetFilterInfo(FILTER_VER_TYPE2, NULL, &hPrefMem, 
                   NULL)
              == FILTER_GRAPHIC)
            {
              /* get filter preferences if specified */
              if (fPreferences && (GetFilterPref!=NULL))
              {
                GetFilterPref(NULL, hwndParent, hPrefMem, 0);
              }
              /* perform import */
              uResult = ImportGR(NULL, &fs, pPictInfo, hPrefMem);
            }
            /* release preference memory as necessary */
            if (hPrefMem != NULL)
            {
              GlobalFree(hPrefMem); 
              hPrefMem = NULL;
            }
          }
          /* clean up */
          FreeLibrary(hFilterLib); 
          hFilterLib = NULL;
          GetFilterInfo = NULL;
          GetFilterPref = NULL;
          ImportGR = NULL;
        }
      }
    }
  }
  /* done */
  return uResult;
}



/***                        ***
 *** PRIVATE IMPLEMENTATION ***
 ***                        ***/

//---------------------------------------------------------------
//FindGraphicImportFilter
//  LPCSTR     lpszExtension      - file extension (file type) to 
//                                  locate filter for
//  LPSTR      lpszDestFilterPath - destination address to store 
//                                  filter path and file name
//  const UINT cchDestFilterPath  - size of desintaion buffer, in 
//                                  characters
//  >BOOL>                        - TRUE if filter located, FALSE 
//                                  otherwise
//---------------------------------------------------------------
BOOL FindGraphicImportFilter(
  LPCSTR     lpszExtension, 
  LPSTR      lpszDestFilterPath, 
  const UINT cchDestFilterPath)
{
  /* TEMPORARY variables */
  FILETIME ftLastWrite = { 0 };
  LPSTR    lpszNextExt = NULL;
  DWORD    dwIndex = 0;
  DWORD    cbData = 0;
  LONG     lResult = 0;
  HKEY     hkeyImport = NULL;
  HKEY     hkeyFilter = NULL;
  char     szKeyName[CCH_MAX_KEY_NAME+1] = "";
  char     szFilterExtensions[CCH_MAX_FILTER_EXT+1] = "";
  BOOL     fFilterFound = FALSE;

  /* init */
  lpszDestFilterPath[0] = NULL;
  if (lpszExtension[0] == '.')
  {
    ++lpszExtension;    //skip leading period
  }
  /* open graphic import key */  
  lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
    "Software\\Microsoft\\Shared Tools\\Graphics Filters\\Import",
    0, 
    KEY_READ, 
    &hkeyImport);
  if (lResult == ERROR_SUCCESS)
  {
    /* enumerate the available import keys */
    cbData = CountOf(szKeyName);
    szKeyName[0] = NULL;
    while (!fFilterFound && (RegEnumKeyEx(
        hkeyImport, 
        dwIndex, 
        szKeyName, 
        &cbData, 
        NULL, 
        NULL, 
        NULL, 
        &ftLastWrite) == ERROR_SUCCESS))
    {
      ++dwIndex;
      /* open the filter key */
      lResult = RegOpenKeyEx(
        hkeyImport, 
        szKeyName, 
        0, 
        KEY_READ, 
        &hkeyFilter);
      if (lResult == ERROR_SUCCESS)
      {
        /* get supported filter extensions */
        cbData = CountOf(szFilterExtensions);
        szFilterExtensions[0] = NULL;
        lResult = RegQueryValueEx(
          hkeyFilter, 
          "ExtensionsEx", 
          NULL, 
          NULL, 
          (LPBYTE)szFilterExtensions, 
          &cbData);
        if (lResult != ERROR_SUCCESS)
        {
          /* ex extensions not found, use default */
          lResult = RegQueryValueEx(
            hkeyFilter, 
            "Extensions", 
            NULL, 
            NULL, 
            (LPBYTE)szFilterExtensions, 
            &cbData);
        }
        if (lResult == ERROR_SUCCESS)
        {
          /* check for specified extension */
          do
          {
            lpszNextExt = strchr(szFilterExtensions, ' ');
            if (lpszNextExt != NULL)
            {
              *lpszNextExt = NULL;
              ++lpszNextExt;
            }
            fFilterFound = lstrcmpi(
              szFilterExtensions, 
              lpszExtension) == 0;
            if (!fFilterFound && (lpszNextExt!=NULL))
            {
              MoveMemory(
                szFilterExtensions,
                lpszNextExt, 
                lstrlen(lpszNextExt) + 1);
            }
          }
          while (!fFilterFound && (lpszNextExt!=NULL));
          if (fFilterFound)
          {
            /* get the filter path */
            cbData = cchDestFilterPath;
            lResult = RegQueryValueEx(
              hkeyFilter, 
              "Path", 
              NULL, 
              NULL, 
              (LPBYTE)lpszDestFilterPath, 
              &cbData);
            fFilterFound = lResult == ERROR_SUCCESS;
          }
        }
        /* close filter key */
        RegCloseKey(hkeyFilter); 
        hkeyFilter = NULL;
      }
      /* prep for next filter key */
      cbData = CountOf(szKeyName);
      szKeyName[0] = NULL;
    }
    /* close import key */
    RegCloseKey(hkeyImport); 
    hkeyImport = NULL;
  }
  /* done */
  return fFilterFound;
}

//---------------------------------------------------------------
//ResolveProcAddress
//---------------------------------------------------------------
FARPROC ResolveProcAddress(
  const HMODULE  hLibrary, 
  const LPCSTR * lpszNames)
{
  /* TEMPORARY variables */
  FARPROC  fn = NULL;
  UINT    uIndex = 0;

  /* attempt to resolve proc name */
  while ((fn==NULL) && (lpszNames[uIndex]!=NULL))
  {
    fn = GetProcAddress(hLibrary, lpszNames[uIndex]);
    ++uIndex;
  }
  /* done */
  return fn;
}
— End of Listing —