See the question and my original answer on StackOverflow

You can use the IShellItemImageFactory interface, something like this:

...
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // need this somewhere when your thread begins, not for every call
...
IShellItemImageFactory* factory;
if (SUCCEEDED(SHCreateItemFromParsingName(path, nullptr, IID_PPV_ARGS(&factory))))
{
    // the GetImage method defines a required size and multiple flags
    // with which you can specify you want the icon only or the thumbnail, etc.
    HBITMAP bmp;
    if (SUCCEEDED(factory->GetImage(SIZE{ 256, 256 }, SIIGBF_ICONONLY, &bmp)))
    {
        ... // do something with the HBITMAP
        DeleteObject(bmp);
    }
    factory->Release();
}

...
CoUninitialize(); // call this each time you successfully called CoInitializeEx