IShellExtInit::Initialize Called by the shell to initialize our contextual menu extension. We need to use this opportunity to look at the files/folders to act upon. @param p_pFolderPIDL Pointer to ITEMIDLIST representing selected folder. @param p_pDataObject Pointer to data object containing information about selected files/folders. @param p_hKeyFileClass Handle to file class key; unused. @retur
| 219 | // @return S_OK if successful, otherwise an error code. |
| 220 | // |
| 221 | [[gsl::suppress(c.128)]] |
| 222 | STDMETHODIMP CPathCopyCopyContextMenuExt::Initialize( |
| 223 | PCIDLIST_ABSOLUTE p_pFolderPIDL, |
| 224 | IDataObject *p_pDataObject, |
| 225 | HKEY /*p_hKeyFileClass*/) |
| 226 | { |
| 227 | HRESULT hRes = S_OK; |
| 228 | |
| 229 | try { |
| 230 | // Make sure we have a data object. |
| 231 | if (p_pDataObject != nullptr) { |
| 232 | // Extract HDROP from data object. |
| 233 | StStgMedium stgMedium; |
| 234 | FORMATETC formatEtc = {CF_HDROP, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; |
| 235 | if (SUCCEEDED(p_pDataObject->GetData(&formatEtc, &stgMedium))) { |
| 236 | // Get number of files included in the selection. |
| 237 | const UINT fileCount = ::DragQueryFileW( |
| 238 | static_cast<HDROP>(stgMedium.Get().hGlobal), 0xFFFFFFFF, 0, 0); |
| 239 | if (fileCount > 0) { |
| 240 | // Pre-allocate space in vector to store files. |
| 241 | m_vFiles.reserve(fileCount); |
| 242 | |
| 243 | // Get each file in turn. |
| 244 | for (UINT i = 0; i < fileCount; ++i) { |
| 245 | const auto bufferSize = ::DragQueryFileW(static_cast<HDROP>(stgMedium.Get().hGlobal), i, nullptr, 0); |
| 246 | std::wstring buffer(bufferSize + 1, L'\0'); |
| 247 | ::DragQueryFileW(static_cast<HDROP>(stgMedium.Get().hGlobal), i, &*buffer.begin(), gsl::narrow<UINT>(buffer.size())); |
| 248 | m_vFiles.emplace_back(buffer.c_str()); |
| 249 | } |
| 250 | } else { |
| 251 | // It's difficult to display a menu item without files to act upon. |
| 252 | hRes = E_FAIL; |
| 253 | } |
| 254 | } |
| 255 | } else if (p_pFolderPIDL != nullptr) { |
| 256 | // No data object, but maybe it's because user clicked on a folder's |
| 257 | // background. Get the folder path from the ID list. |
| 258 | std::wstring buffer(MAX_PATH + 1, L'\0'); |
| 259 | if (::SHGetPathFromIDList(p_pFolderPIDL, &*buffer.begin()) != FALSE) { |
| 260 | m_vFiles.emplace_back(buffer.c_str()); |
| 261 | } else { |
| 262 | // Nothing like that either, problem. |
| 263 | hRes = E_FAIL; |
| 264 | } |
| 265 | } else { |
| 266 | hRes = E_POINTER; |
| 267 | } |
| 268 | } catch (...) { |
| 269 | hRes = E_UNEXPECTED; |
| 270 | } |
| 271 | |
| 272 | if (SUCCEEDED(hRes)) { |
| 273 | // Check if files and/or folders are selected. |
| 274 | m_FilesSelected = std::any_of(m_vFiles.cbegin(), m_vFiles.cend(), |
| 275 | [](const auto& path) { return !PCC::PluginUtils::IsDirectory(path); }); |
| 276 | m_FoldersSelected = std::any_of(m_vFiles.cbegin(), m_vFiles.cend(), |
| 277 | [](const auto& path) { return PCC::PluginUtils::IsDirectory(path); }); |
| 278 | } |