title: How to Properly Use and Instantiate existing Preview Handlers
body: <p>I am trying to use existing preview handlers to display previews of files.</p>
  <p>I wrote a simple test program to 1) find the CLSID of the preview handler for a given file, 2) instantiate the preview handler, 3) initialize it, either by stream or file and 4) render the preview on a basic window.</p>
  <p>This works. More or less.</p>
  <p>It works just fine for the pdf preview handler provided by adobe acrobat reader, but doesn't work with the windows provided pdf preview handler (CLSID <code>{3A84F9C2-6164-485C-A7D9-4B27F8AC009E}</code>, provided by edge in PdfPreviewHandler.dll, just for reference). (It doesn't fail anywhere, it just doesnt work and doesn't render a preview, see images).
  <a href="https://i.stack.imgur.com/L8k8G.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/L8k8G.png" alt="windows provided pdf preview handler" /></a> <a href="https://i.stack.imgur.com/0734P.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/0734P.png" alt="acrobat reader pdf handler" /></a></p>
  <p>Same situation for the microsoft office preview handlers for excel (.xlsx) and power point (.pptx) files.</p>
  <p>For word (.docx) files, it fails completely. The IInitializeWithFile call in line 106 fails with &quot;Unspecified Error&quot; (HRESULT 0x80004005).</p>
  <p>A bunch of other preview handlers work just fine, some initialized by stream, some by file (e.g. windows provided handler for html and text files).</p>
  <p>I don't really know what the issue could be or where i even should start looking, any input on this would be appreciated.</p>
  <p>compile with <code>cl /std:c++20 test.cpp ole32.lib shlwapi.lib user32.lib /EHsc</code>, expects file path as first executable argument.</p>
  <pre><code>#include &lt;filesystem&gt;
  #include &lt;array&gt;
  #include &lt;cassert&gt;
  #include &lt;stdexcept&gt;
  #include &lt;iostream&gt;
  
  #include &quot;Windows.h&quot;
  #include &quot;ShObjIdl.h&quot;
  #include &quot;shlwapi.h&quot;
  #include &quot;objbase.h&quot;
  
  #define checkHresult(res) (checkHresult_(res, __LINE__, __FILE__))
  
  void checkHresult_(HRESULT res, int line, const char *file){
      if(res != S_OK){
          std::stringstream msg;
          msg &lt;&lt; file &lt;&lt; ':' &lt;&lt; line &lt;&lt; &quot;: 0x&quot; &lt;&lt; std::hex &lt;&lt; res &lt;&lt; ' ';
          LPSTR errMsg;
          if(FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 
                            nullptr, 
                            res, 
                            MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), 
                            reinterpret_cast&lt;LPSTR&gt;(&amp;errMsg), 
                            0, 
                            nullptr)){
              msg &lt;&lt; errMsg;
              LocalFree(errMsg);
          }
          throw std::runtime_error(msg.str());
      }
  }
  
  CLSID getShellExtensionClsidForFileType(const std::wstring&amp; extension, const GUID&amp; interfaceID){
      HRESULT res;
      std::array&lt;wchar_t, 39&gt; ifIdWStr;
      int written;
      written = StringFromGUID2(interfaceID, ifIdWStr.data(), ifIdWStr.size());
      if(written == 0){
          checkHresult(HRESULT_FROM_WIN32(GetLastError())); //StringFromGUID2 should not fail
      }
  
      std::array&lt;wchar_t, 39&gt; extIdWStr;
      DWORD extIdWStrSize = extIdWStr.size();
      res = AssocQueryStringW(ASSOCF_INIT_DEFAULTTOSTAR, 
                              ASSOCSTR_SHELLEXTENSION,
                              extension.c_str(),
                              ifIdWStr.data(),
                              extIdWStr.data(),
                              &amp;extIdWStrSize);
      checkHresult(res);
      
      CLSID extId;
      res = IIDFromString(extIdWStr.data(), &amp;extId);
      checkHresult(res); //IIDFromString should not fail
      std::wcout &lt;&lt; &quot;preview handler clsid: &quot; &lt;&lt; extIdWStr.data() &lt;&lt; '\n';
      return(extId);
  }
  
  
  IPreviewHandler* getIPreviewHandlerInterfaceForType(const std::wstring&amp; extension){
      HRESULT res;
      //get the CLSID for the preview handler for the specified fily type
      CLSID iPreviewHandlerClsid(getShellExtensionClsidForFileType(extension, IID_IPreviewHandler));
      IPreviewHandler *iPreviewHandler;
      res = CoCreateInstance(iPreviewHandlerClsid, 
                             nullptr, 
                             CLSCTX_LOCAL_SERVER, 
                             IID_IPreviewHandler, 
                             reinterpret_cast&lt;LPVOID*&gt;(&amp;iPreviewHandler));
      checkHresult(res);
      return(iPreviewHandler);
  }
  
  int wmain(int argc, wchar_t *argv[]){
      try{
          if(argc != 2){
              return(1);
          }
          HRESULT res;
  
          res = CoInitialize(nullptr);
          checkHresult(res);
  
          std::filesystem::path filePath(argv[1]);
          filePath.make_preferred();
  
          //Instantiate the preview handler for the specified file type
          IPreviewHandler *iPreviewHandler = getIPreviewHandlerInterfaceForType(filePath.extension());
  
          IInitializeWithStream *iInitializeWithStream;
          IInitializeWithFile *iInitializeWithFile;
  
          iPreviewHandler-&gt;QueryInterface(IID_IInitializeWithStream, reinterpret_cast&lt;LPVOID*&gt;(&amp;iInitializeWithStream));
          iPreviewHandler-&gt;QueryInterface(IID_IInitializeWithFile, reinterpret_cast&lt;LPVOID*&gt;(&amp;iInitializeWithFile));
  
          //Initialize preview handler, preferably with a stream
          if(iInitializeWithStream){
              IStream *iStream;
              res = SHCreateStreamOnFileEx(filePath.c_str(), STGM_READ | STGM_SHARE_DENY_WRITE, 0, false, nullptr, &amp;iStream);
              checkHresult(res);
              res = iInitializeWithStream-&gt;Initialize(iStream, STGM_READ);
              checkHresult(res);
              std::cout &lt;&lt; &quot;Initialized with Stream\n&quot;;
          }else if(iInitializeWithFile){
              res = iInitializeWithFile-&gt;Initialize(filePath.c_str(), STGM_READ);
              checkHresult(res);
              std::cout &lt;&lt; &quot;Initialized with File\n&quot;;
          }else{
              checkHresult(E_NOINTERFACE);
          }
  
          //create basic window
          WNDCLASSW wndClass;
          wndClass.style = 0;
          wndClass.lpfnWndProc = DefWindowProcW;
          wndClass.cbClsExtra = 0;
          wndClass.cbWndExtra = 0;
          wndClass.hInstance = GetModuleHandleA(nullptr);
          wndClass.hIcon = nullptr;
          wndClass.hCursor = nullptr;
          wndClass.hbrBackground = nullptr;
          wndClass.lpszMenuName = nullptr;
          wndClass.lpszClassName = L&quot;test&quot;;
  
          ATOM wndAtom = RegisterClassW(&amp;wndClass);
          if(wndAtom == 0){
              checkHresult(HRESULT_FROM_WIN32(GetLastError()));
          }
          HWND window = CreateWindowExW(0, 
                                        L&quot;test&quot;, 
                                        L&quot;&quot;, 
                                        WS_VISIBLE, 
                                        CW_USEDEFAULT, 
                                        CW_USEDEFAULT, 
                                        CW_USEDEFAULT, 
                                        CW_USEDEFAULT, 
                                        0, 
                                        0, 
                                        wndClass.hInstance, 
                                        nullptr);
          if(window == nullptr){
              checkHresult(HRESULT_FROM_WIN32(GetLastError()));
          }
  
          ShowWindow(window, SW_NORMAL);
  
          RECT rect;
          GetClientRect(window, &amp;rect);
          res = iPreviewHandler-&gt;SetWindow(window, &amp;rect);
          checkHresult(res);
          res = iPreviewHandler-&gt;DoPreview();
  
          MSG msg;
          while(GetMessageW(&amp;msg, nullptr, 0, 0) &gt; 0){
              TranslateMessage(&amp;msg);
              DispatchMessage(&amp;msg);
          }
      }catch(std::runtime_error err){
          std::cout &lt;&lt; err.what();
      }
  }
  </code></pre>