I'm using the following code to retrieve multiple file selection via UI:
CFileDialog fd(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,
NULL, hParentWnd ? CWnd::FromHandle(hParentWnd) : NULL);
fd.m_pOFN->Flags |= OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_NODEREFERENCELINKS;
int nLnBuff = 32767;
TCHAR* pBuffFileSelect = new TCHAR[nLnBuff];
memset(pBuffFileSelect, 0, nLnBuff * sizeof(TCHAR));
fd.m_ofn.lpstrFile = pBuffFileSelect;
fd.m_ofn.nMaxFile = nLnBuff;
if(fd.DoModal() == IDOK)
{
POSITION fileNamesPosition = fd.GetStartPosition();
while(fileNamesPosition != NULL)
{
CString strSelPath = fd.GetNextPathName(fileNamesPosition);
TRACE("path: %s\n", CStringA(strSelPath));
}
}
delete[] pBuffFileSelect;
So when I try it on my PC, I run the method above and when the "Open File" dialog open up, just as a test, I navigated to my desktop and selected all files using Ctrl+A shortcut and then clicked Open. As a result I started getting the following paths:
The first path is a link, which is correct (it exists on my Public desktop):
"C:\Users\Public\Desktop\avp.lnk"
But then the second path is wrong. It gives me:
"C:\Users\Public\Desktop\1.txt"
when it's supposed to be (for the desktop that I picked):
"C:\Users\UserName\Desktop\1.txt"
and then every consecutive path has "Public" instead of "UserName".
I should point out that I have several user accounts set up on this PC and the one that I'm testing this method from is a Standard user account. The app that I'm running this method from is not running elevated (or with regular user privileges) so it should not have access to other user accounts anyway.
So what am I doing wrong here?
Checked the sources, and GetOpenFileName assumes that all the items are in fact in the same file path. This isn't true for the Desktop (there are items in different paths merged into one shell view), and so you'll see the bad behavior.
The solution is to use the Common Item dialogs, which use the shell namespace rather than file system paths. All the desktop items are in a common shell path, and then you can use IShellItem::GetDisplayName to convert to a file system path.
Unfortunately, MFC doesn't have a wrapper for the common item dialog, so you'll have to manage that yourself.