2
 void file_explore(std::wstring str) {
     ITEMIDLIST *pIDL = ILCreateFromPath(str.c_str());
     if ( NULL != pIDL ) {
         SHOpenFolderAndSelectItems(pIDL , 0 , 0 , 0);
         ILFree(pIDL);
     } else {
         std::wstring p = str.substr(0 , str.find_last_of('\\'));
         ShellExecute(NULL , L"explore" , p.c_str() , NULL , NULL , SW_SHOWNORMAL);
     }
 }    

The above compiles without warning for 32bit but with 64bit I get warning c4090 however the docs: https://msdn.microsoft.com/en-us/library/k77bkb8d.aspx state that this is a c error and I will get C2440 for c++ yet I'm using c++.

The line of code complained of is:

 ITEMIDLIST *pIDL = ILCreateFromPath(str.c_str());

How to fix this issue for 64bit builds?

IInspectable
  • 46,945
  • 8
  • 85
  • 181
User666
  • 121
  • 1
  • 10
  • 1
    Your project probably defined `STRICT_TYPED_ITEMIDS`, but you are using a generic `ITEMIDLIST*`. [ILCreateFromPath](https://msdn.microsoft.com/en-us/library/windows/desktop/dd378420.aspx) returns a `PIDLIST_ABSOLUTE`. That's one of the strict [ITEMIDLIST](https://msdn.microsoft.com/en-us/library/windows/desktop/bb773321.aspx), and you should assign it to the same type. – IInspectable Feb 17 '17 at 17:42
  • 2
    You can get rid of the warning by using the type recommended by the MSDN article: `PIDLIST_ABSOLUTE pIDL = ILCreateFromPath(...); Using LPITEMIDLIST solves it as well. – Hans Passant Feb 17 '17 at 18:57
  • this is faster warning about `str.c_str()` convert to `PCWSTR` instead about `ITEMIDLIST*` – RbMm Feb 17 '17 at 21:31
  • @RbMm: `std::wstring::c_str()` has type `const wchar_t*`. That's the same as `PCWSTR`. There is no mismatch (assuming a Unicode build, which the OP is obviously doing). – IInspectable Feb 17 '17 at 22:14

2 Answers2

6

LPITEMIDLIST is defined as typedef ITEMIDLIST __unaligned *LPITEMIDLIST, so accepting the result as ITEMIDLIST * loses that __unaligned modifier. I am not sure how this relates to 32-bit versus 64-bit.

As Hans Passant commented, using the typedef solves the issue. In my case, I'm using std::unique_ptr, which wants the base type rather than the pointer, so I needed a non-pointer typedef. Because it might be of tangential interest for people stumbling upon this answer, I'll put in how I am making use of a std::unique_ptr with ILCreateFromPath, including the custom deleter for fun:

auto deleter = [](LPITEMIDLIST ptr) { ILFree(ptr); };
using itemidlistptr_t = std::unique_ptr<
    std::remove_ptr_t<LPITEMIDLIST>, decltype(deleter)>;
auto dir = itemidlistptr_t(ILCreateFromPathW(folder.c_str()), deleter);

Using std::remove_pointer_t is a bit roundabout, but I like it here rather than mentioning __unaligned myself directly.

McMustard
  • 159
  • 2
  • 5
0

I have had a similar issue while been declared _X86_ macro definition instead of _AMD64_.

Andry
  • 2,273
  • 29
  • 28