コード例 #1
0
ファイル: Artist.cpp プロジェクト: derobert/debianlink-xbmc
bool CArtist::Save(TiXmlNode *node, const CStdString &tag, const CStdString& strPath)
{
  if (!node) return false;

  // we start with a <tag> tag
  TiXmlElement artistElement(tag.c_str());
  TiXmlNode *artist = node->InsertEndChild(artistElement);

  if (!artist) return false;

  XMLUtils::SetString(artist,       "name", strArtist);
  CStdStringArray array;
  StringUtils::SplitString(strGenre, g_advancedSettings.m_musicItemSeparator,array);
  for (unsigned int i=0;i<array.size();++i)
    XMLUtils::SetString(artist,       "genre", array[i]);
  array.clear();
  StringUtils::SplitString(strStyles, g_advancedSettings.m_musicItemSeparator,array);
  for (unsigned int i=0;i<array.size();++i)
    XMLUtils::SetString(artist,      "style", array[i]);
  array.clear();
  StringUtils::SplitString(strMoods, g_advancedSettings.m_musicItemSeparator,array);
  for (unsigned int i=0;i<array.size();++i)
    XMLUtils::SetString(artist,      "mood", array[i]);
  array.clear();
  StringUtils::SplitString(strYearsActive, g_advancedSettings.m_musicItemSeparator,array);
  for (unsigned int i=0;i<array.size();++i)
    XMLUtils::SetString(artist, "yearsactive", array[i]);
  XMLUtils::SetString(artist,        "born", strBorn);
  XMLUtils::SetString(artist,      "formed", strFormed);
  XMLUtils::SetString(artist, "instruments", strInstruments);
  XMLUtils::SetString(artist,   "biography", strBiography);
  XMLUtils::SetString(artist,        "died", strDied);
  XMLUtils::SetString(artist,   "disbanded", strDisbanded);
  XMLUtils::SetString(artist,      "thumbs", thumbURL.m_xml);
  XMLUtils::SetString(artist,        "path", strPath);
  if (fanart.m_xml.size())
  {
    TiXmlDocument doc;
    doc.Parse(fanart.m_xml);
    artist->InsertEndChild(*doc.RootElement());
  }

  // albums
  for (vector< pair<CStdString,CStdString> >::const_iterator it = discography.begin(); it != discography.end(); ++it)
  {
    // add a <album> tag
    TiXmlElement cast("album");
    TiXmlNode *node = artist->InsertEndChild(cast);
    TiXmlElement title("title");
    TiXmlNode *titleNode = node->InsertEndChild(title);
    TiXmlText name(it->first);
    titleNode->InsertEndChild(name);
    TiXmlElement year("year");
    TiXmlNode *yearNode = node->InsertEndChild(year);
    TiXmlText name2(it->second);
    yearNode->InsertEndChild(name2);
  }

  return true;
}
コード例 #2
0
TEST(TestStringUtils, JoinString)
{
  CStdString refstr, varstr;
  CStdStringArray strarray;

  strarray.push_back("a");
  strarray.push_back("b");
  strarray.push_back("c");
  strarray.push_back("de");
  strarray.push_back(",");
  strarray.push_back("fg");
  strarray.push_back(",");
  refstr = "a,b,c,de,,,fg,,";
  StringUtils::JoinString(strarray, ",", varstr);
  EXPECT_STREQ(refstr.c_str(), varstr.c_str());

  strarray.clear();
  varstr.clear();
  strarray.push_back("g");
  strarray.push_back("h");
  strarray.push_back("i");
  strarray.push_back("jk,");
  strarray.push_back(",");
  strarray.push_back("lmn,,");
  strarray.push_back(",");
  refstr = "g,h,i,jk,,,,lmn,,,,";
  varstr = StringUtils::JoinString(strarray, ",");
  EXPECT_STREQ(refstr.c_str(), varstr.c_str());
}
コード例 #3
0
TEST(TestStringUtils, SplitString)
{
  CStdStringArray varresults;

  EXPECT_EQ(9, StringUtils::SplitString("a,b,c,de,,,fg,,", ",", varresults));
  EXPECT_STREQ("a", varresults.at(0).c_str());
  EXPECT_STREQ("b", varresults.at(1).c_str());
  EXPECT_STREQ("c", varresults.at(2).c_str());
  EXPECT_STREQ("de", varresults.at(3).c_str());
  EXPECT_STREQ("", varresults.at(4).c_str());
  EXPECT_STREQ("", varresults.at(5).c_str());
  EXPECT_STREQ("fg", varresults.at(6).c_str());
  EXPECT_STREQ("", varresults.at(7).c_str());
  EXPECT_STREQ("", varresults.at(8).c_str());

  varresults.clear();
  varresults = StringUtils::SplitString("g,h,ij,k,lm,,n", ",");
  EXPECT_STREQ("g", varresults.at(0).c_str());
  EXPECT_STREQ("h", varresults.at(1).c_str());
  EXPECT_STREQ("ij", varresults.at(2).c_str());
  EXPECT_STREQ("k", varresults.at(3).c_str());
  EXPECT_STREQ("lm", varresults.at(4).c_str());
  EXPECT_STREQ("", varresults.at(5).c_str());
  EXPECT_STREQ("n", varresults.at(6).c_str());
}
コード例 #4
0
// Splits the string input into pieces delimited by delimiter.
// if 2 delimiters are in a row, it will include the empty string between them.
// added MaxStrings parameter to restrict the number of returned substrings (like perl and python)
int StringUtils::SplitString(const CStdString& input, const CStdString& delimiter, CStdStringArray &results, unsigned int iMaxStrings /* = 0 */)
{
  int iPos = -1;
  int newPos = -1;
  int sizeS2 = delimiter.GetLength();
  int isize = input.GetLength();

  results.clear();

  vector<unsigned int> positions;

  newPos = input.Find (delimiter, 0);

  if ( newPos < 0 )
  {
    results.push_back(input);
    return 1;
  }

  while ( newPos > iPos )
  {
    positions.push_back(newPos);
    iPos = newPos;
    newPos = input.Find (delimiter, iPos + sizeS2);
  }

  // numFound is the number of delimiters which is one less
  // than the number of substrings
  unsigned int numFound = positions.size();
  if (iMaxStrings > 0 && numFound >= iMaxStrings)
    numFound = iMaxStrings - 1;

  for ( unsigned int i = 0; i <= numFound; i++ )
  {
    CStdString s;
    if ( i == 0 )
    {
      if ( i == numFound )
        s = input;
      else
        s = input.Mid( i, positions[i] );
    }
    else
    {
      int offset = positions[i - 1] + sizeS2;
      if ( offset < isize )
      {
        if ( i == numFound )
          s = input.Mid(offset);
        else if ( i > 0 )
          s = input.Mid( positions[i - 1] + sizeS2,
                         positions[i] - positions[i - 1] - sizeS2 );
      }
    }
    results.push_back(s);
  }
  // return the number of substrings
  return results.size();
}
コード例 #5
0
ファイル: StringUtils.cpp プロジェクト: Avoidnf8/xbmc-fork
// Splits the string input into pieces delimited by delimiter.
// if 2 delimiters are in a row, it will include the empty string between them.
int StringUtils::SplitString(const CStdString& input, const CStdString& delimiter, CStdStringArray &results)
{
  int iPos = -1;
  int newPos = -1;
  int sizeS2 = delimiter.GetLength();
  int isize = input.GetLength();

  results.clear();

  //CArray positions;
  vector<unsigned int> positions;

  newPos = input.Find (delimiter, 0);

  if ( newPos < 0 )
  {
    results.push_back(input);
    return 1;
  }

  int numFound = 1;

  while ( newPos > iPos )
  {
    numFound++;
    positions.push_back(newPos);
    iPos = newPos;
    newPos = input.Find (delimiter, iPos + sizeS2);
  }

  for ( unsigned int i = 0; i <= positions.size(); i++ )
  {
    CStdString s;
    if ( i == 0 )
    {
      if (i == positions.size())
        s = input;
      else
        s = input.Mid( i, positions[i] );
    }
    else
    {
      int offset = positions[i - 1] + sizeS2;
      if ( offset < isize )
      {
        if ( i == positions.size() )
          s = input.Mid(offset);
        else if ( i > 0 )
          s = input.Mid( positions[i - 1] + sizeS2,
                         positions[i] - positions[i - 1] - sizeS2 );
      }
    }
    results.push_back(s);
  }
  return numFound;
}
コード例 #6
0
	bool CASCIIManager::readFile_using_std_stream(CStdString strFileName, CStdStringArray &aRighe /*, UV_MFC::CDlg_Progresso *pDlg*/)		///< Leggo da file.
	{
		std::wifstream			myfile(strFileName);
		std::streampos			pos_begin = std::ios::beg;
		std::streampos			pos_curr;
		std::wstring			line;
		CStdString				strLine;
		int						fileLen = 0;
		int						nI = 0, nCont = 3500;
		ULONGLONG				nPosition;
		double					dPerc, dPerc1;
		CStdString				strFase;

		if (myfile.is_open())
		{
			// get length of file:
			myfile.seekg(0, myfile.end);
			fileLen = (int)myfile.tellg();
			myfile.seekg(0, myfile.beg);

			pos_curr = myfile.tellg();
			aRighe.clear();
			while (getline(myfile, line))
			{
				pos_curr = myfile.tellg();

				// std::cout << line << '\n';
				strLine.Format(_T("%s"), line.c_str());
				aRighe.push_back(strLine);
				nI++;

				//if (pDlg && nI > nCont)
				//{
				//	nPosition = pos_curr.seekpos();
				//	dPerc = nPosition / (double)fileLen;
				//	dPerc = max(0, min(1, dPerc));
				//	dPerc1 = pDlg->m_dPercMin + dPerc*(pDlg->m_dPercMax - pDlg->m_dPercMin);

				//	pDlg->SetPos(dPerc1);
				//	strFase.Format(_T("[%d/%d] Reading rows (%.1lf%%)"), pDlg->m_nFaseCurr, pDlg->m_nFaseTot, 100.0*dPerc);
				//	pDlg->SetFase(strFase);
				//	nI = 0;
				//	if (!pDlg->m_bContinua)
				//	{
				//		myfile.close();
				//		return false;
				//	}
				//}
			}
			myfile.close();
		}
		return true;
	}
コード例 #7
0
ファイル: AdvancedSettings.cpp プロジェクト: Rocky5/XBMC4Kids
void CAdvancedSettings::GetCustomRegexps(TiXmlElement *pRootElement, CStdStringArray& settings)
{
  TiXmlElement *pElement = pRootElement;
  while (pElement)
  {
    int iAction = 0; // overwrite
    // for backward compatibility
    const char* szAppend = pElement->Attribute("append");
    if ((szAppend && stricmp(szAppend, "yes") == 0))
      iAction = 1;
    // action takes precedence if both attributes exist
    const char* szAction = pElement->Attribute("action");
    if (szAction)
    {
      iAction = 0; // overwrite
      if (stricmp(szAction, "append") == 0)
        iAction = 1; // append
      else if (stricmp(szAction, "prepend") == 0)
        iAction = 2; // prepend
    }
    if (iAction == 0)
      settings.clear();
    TiXmlNode* pRegExp = pElement->FirstChild("regexp");
    int i = 0;
    while (pRegExp)
    {
      if (pRegExp->FirstChild())
      {
        CStdString regExp = pRegExp->FirstChild()->Value();
        regExp.MakeLower();
        if (iAction == 2)
          settings.insert(settings.begin() + i++, 1, regExp);
        else
          settings.push_back(regExp);
      }
      pRegExp = pRegExp->NextSibling("regexp");
    }

    pElement = pElement->NextSiblingElement(pRootElement->Value());
  }
}
コード例 #8
0
ファイル: ExternalPlayer.cpp プロジェクト: Saddamisalami/xbmc
void CExternalPlayer::GetCustomRegexpReplacers(TiXmlElement *pRootElement,
                                               CStdStringArray& settings)
{
  int iAction = 0; // overwrite
  // for backward compatibility
  const char* szAppend = pRootElement->Attribute("append");
  if ((szAppend && stricmp(szAppend, "yes") == 0))
    iAction = 1;
  // action takes precedence if both attributes exist
  const char* szAction = pRootElement->Attribute("action");
  if (szAction)
  {
    iAction = 0; // overwrite
    if (stricmp(szAction, "append") == 0)
      iAction = 1; // append
    else if (stricmp(szAction, "prepend") == 0)
      iAction = 2; // prepend
  }
  if (iAction == 0)
    settings.clear();

  TiXmlElement* pReplacer = pRootElement->FirstChildElement("replacer");
  int i = 0;
  while (pReplacer)
  {
    if (pReplacer->FirstChild())
    {
      const char* szGlobal = pReplacer->Attribute("global");
      const char* szStop = pReplacer->Attribute("stop");
      bool bGlobal = szGlobal && stricmp(szGlobal, "true") == 0;
      bool bStop = szStop && stricmp(szStop, "true") == 0;

      CStdString strMatch;
      CStdString strPat;
      CStdString strRep;
      XMLUtils::GetString(pReplacer,"match",strMatch);
      XMLUtils::GetString(pReplacer,"pat",strPat);
      XMLUtils::GetString(pReplacer,"rep",strRep);

      if (!strPat.IsEmpty() && !strRep.IsEmpty())
      {
        CLog::Log(LOGDEBUG,"  Registering replacer:");
        CLog::Log(LOGDEBUG,"    Match:[%s] Pattern:[%s] Replacement:[%s]", strMatch.c_str(), strPat.c_str(), strRep.c_str());
        CLog::Log(LOGDEBUG,"    Global:[%s] Stop:[%s]", bGlobal?"true":"false", bStop?"true":"false");
        // keep literal commas since we use comma as a seperator
        strMatch.Replace(",",",,");
        strPat.Replace(",",",,");
        strRep.Replace(",",",,");

        CStdString strReplacer = strMatch + " , " + strPat + " , " + strRep + " , " + (bGlobal ? "g" : "") + (bStop ? "s" : "");
        if (iAction == 2)
          settings.insert(settings.begin() + i++, 1, strReplacer);
        else
          settings.push_back(strReplacer);
      }
      else
      {
        // error message about missing tag
        if (strPat.IsEmpty())
          CLog::Log(LOGERROR,"  Missing <Pat> tag");
        else
          CLog::Log(LOGERROR,"  Missing <Rep> tag");
      }
    }

    pReplacer = pReplacer->NextSiblingElement("replacer");
  }
}
コード例 #9
0
int CGUIWindowAddonBrowser::SelectAddonID(const vector<ADDON::TYPE> &types, CStdStringArray &addonIDs, bool showNone /*= false*/, bool multipleSelection /*= true*/)
{
  CGUIDialogSelect *dialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT);
  if (!dialog)
    return 0;

  CFileItemList items;
  CStdString heading;
  int iTypes = 0;
  for (vector<ADDON::TYPE>::const_iterator it = types.begin(); it != types.end(); ++it)
  {
    if (*it == ADDON_UNKNOWN)
      continue;
    ADDON::VECADDONS addons;
    iTypes++;
    if (*it == ADDON_AUDIO)
      CAddonsDirectory::GetScriptsAndPlugins("audio",addons);
    else if (*it == ADDON_EXECUTABLE)
      CAddonsDirectory::GetScriptsAndPlugins("executable",addons);
    else if (*it == ADDON_IMAGE)
      CAddonsDirectory::GetScriptsAndPlugins("image",addons);
    else if (*it == ADDON_VIDEO)
      CAddonsDirectory::GetScriptsAndPlugins("video",addons);
    else
      CAddonMgr::Get().GetAddons(*it, addons);
    for (ADDON::IVECADDONS it2 = addons.begin() ; it2 != addons.end() ; ++it2)
    {
      CFileItemPtr item(CAddonsDirectory::FileItemFromAddon(*it2, ""));
      if (!items.Contains(item->GetPath()))
        items.Add(item);
    }

    if (!heading.IsEmpty())
      heading += ", ";
    heading += TranslateType(*it, true);
  }

  if (iTypes == 0)
    return 0;

  dialog->SetHeading(heading);
  dialog->Reset();
  dialog->SetUseDetails(true);
  if (multipleSelection)
    showNone = false;
  if (multipleSelection || iTypes > 1)
    dialog->EnableButton(true, 186);
  else
    dialog->EnableButton(true, 21452);
  if (showNone)
  {
    CFileItemPtr item(new CFileItem("", false));
    item->SetLabel(g_localizeStrings.Get(231));
    item->SetLabel2(g_localizeStrings.Get(24040));
    item->SetIconImage("DefaultAddonNone.png");
    item->SetSpecialSort(SortSpecialOnTop);
    items.Add(item);
  }
  items.Sort(SORT_METHOD_LABEL, SortOrderAscending);

  if (addonIDs.size() > 0)
  {
    for (CStdStringArray::const_iterator it = addonIDs.begin(); it != addonIDs.end() ; it++)
    {
      CFileItemPtr item = items.Get(*it);
      if (item)
        item->Select(true);
    }
  }
  dialog->SetItems(&items);
  dialog->SetMultiSelection(multipleSelection);
  dialog->DoModal();
  if (!multipleSelection && iTypes == 1 && dialog->IsButtonPressed())
  { // switch to the addons browser.
    vector<CStdString> params;
    params.push_back("addons://all/"+TranslateType(types[0],false)+"/");
    params.push_back("return");
    g_windowManager.ActivateWindow(WINDOW_ADDON_BROWSER, params);
    return 2;
  }
  if (!dialog->IsConfirmed())
    return 0;
  addonIDs.clear();
  const CFileItemList& list = dialog->GetSelectedItems();
  for (int i = 0 ; i < list.Size() ; i++)
    addonIDs.push_back(list.Get(i)->GetPath());
  return 1;
}
コード例 #10
0
ファイル: GUIWindowAddonBrowser.cpp プロジェクト: Dolmio/xbmc
int CGUIWindowAddonBrowser::SelectAddonID(ADDON::TYPE type, CStdStringArray &addonIDs, bool showNone /*= false*/, bool multipleSelection /*= true*/)
{
  CGUIDialogSelect *dialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT);
  if (type == ADDON_UNKNOWN || !dialog)
    return 0;

  ADDON::VECADDONS addons;
  if (type == ADDON_AUDIO)
    CAddonsDirectory::GetScriptsAndPlugins("audio",addons);
  else if (type == ADDON_EXECUTABLE)
    CAddonsDirectory::GetScriptsAndPlugins("executable",addons);
  else if (type == ADDON_IMAGE)
    CAddonsDirectory::GetScriptsAndPlugins("image",addons);
  else if (type == ADDON_VIDEO)
    CAddonsDirectory::GetScriptsAndPlugins("video",addons);
  else
    CAddonMgr::Get().GetAddons(type, addons);

  CFileItemList items;
  for (ADDON::IVECADDONS i = addons.begin(); i != addons.end(); ++i)
    items.Add(CAddonsDirectory::FileItemFromAddon(*i, ""));

  dialog->SetHeading(TranslateType(type, true));
  dialog->Reset();
  dialog->SetUseDetails(true);
  if (multipleSelection)
  {
    showNone = false;
    dialog->EnableButton(true, 186);
  }
  else
    dialog->EnableButton(true, 21452);
  if (showNone)
  {
    CFileItemPtr item(new CFileItem("", false));
    item->SetLabel(g_localizeStrings.Get(231));
    item->SetLabel2(g_localizeStrings.Get(24040));
    item->SetIconImage("DefaultAddonNone.png");
    item->SetSpecialSort(SORT_ON_TOP);
    items.Add(item);
  }
  items.Sort(SORT_METHOD_LABEL, SORT_ORDER_ASC);

  if (addonIDs.size() > 0)
  {
    for (CStdStringArray::const_iterator it = addonIDs.begin(); it != addonIDs.end() ; it++)
    {
      CFileItemPtr item = items.Get(*it);
      if (item)
        item->Select(true);
    }
  }
  dialog->SetItems(&items);
  dialog->SetMultiSelection(multipleSelection);
  dialog->DoModal();
  if (!multipleSelection && dialog->IsButtonPressed())
  { // switch to the addons browser.
    vector<CStdString> params;
    params.push_back("addons://all/"+TranslateType(type,false)+"/");
    params.push_back("return");
    g_windowManager.ActivateWindow(WINDOW_ADDON_BROWSER, params);
    return 2;
  }
  if (!multipleSelection && dialog->GetSelectedLabel() == -1)
    return 0;
  addonIDs.clear();
  const CFileItemList& list = dialog->GetSelectedItems();
  for (int i = 0 ; i < list.Size() ; i++)
    addonIDs.push_back(list.Get(i)->GetPath());
  return 1;
}
コード例 #11
0
void CMusikSourcesCtrl::DoDrag( CMusikPropTreeItem* pItem )
{
    if ( !pItem )
        return;

    COleDataSource datasrc;
    HGLOBAL        hgDrop;
    DROPFILES*     pDrop;
    CStringList    lsDraggedFiles;
    POSITION       pos;
    CString        sFile;
    UINT           uBuffSize = 0;
    TCHAR*         pszBuff;
    FORMATETC      etc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };

    // get a list of filenames with the currently
    // selected items...
    CStdStringArray files;

    int nMode = pItem->GetPlaylistType();

    // standard playlist dragged
    if ( nMode == MUSIK_PLAYLIST_TYPE_STANDARD )
        m_Library->GetStdPlaylistFns( pItem->GetPlaylistID(), files, false );

    // now playing dragged..
    else if ( nMode == MUSIK_SOURCES_TYPE_NOWPLAYING )
    {
        if ( m_Player->GetPlaylist() )
        {
            m_Library->BeginTransaction();
            for ( size_t i = 0; i < m_Player->GetPlaylist()->GetCount(); i++ )
                files.push_back( m_Player->GetPlaylist()->GetField( i, MUSIK_LIBRARY_TYPE_FILENAME ) );
            m_Library->EndTransaction();
        }
    }

    // library playlist dragged
    else if ( nMode == MUSIK_SOURCES_TYPE_LIBRARY )
    {
        CMainFrame* pMain = (CMainFrame*)m_Parent;
        if ( pMain->m_LibPlaylist )
        {
            m_Library->BeginTransaction();
            for ( size_t i = 0; i < pMain->m_LibPlaylist->GetCount(); i++ )
                files.push_back( pMain->m_LibPlaylist->GetField( i, MUSIK_LIBRARY_TYPE_FILENAME ) );
            m_Library->EndTransaction();
        }
    }

    else if ( nMode == MUSIK_PLAYLIST_TYPE_DYNAMIC )
        MessageBox( "This operation is not supported yet.", "Musik", MB_ICONINFORMATION | MB_OK );


    if ( !files.size() )
        return;

    // CStringList containing files
    for ( size_t i = 0; i < files.size(); i++ )
    {
        lsDraggedFiles.AddTail( files.at( i ) );
        uBuffSize += files.at( i ).GetLength() + 1;
    }

    files.clear();

    // Add 1 extra for the final null char, and the size of the DROPFILES struct.
    uBuffSize = sizeof(DROPFILES) + sizeof(TCHAR) * (uBuffSize + 1);

    // Allocate memory from the heap for the DROPFILES struct.
    hgDrop = GlobalAlloc ( GHND | GMEM_SHARE, uBuffSize );

    if ( !hgDrop )
        return;

    pDrop = (DROPFILES*) GlobalLock ( hgDrop );

    if ( !pDrop )
    {
        GlobalFree ( hgDrop );
        return;
    }

    // Fill in the DROPFILES struct.
    pDrop->pFiles = sizeof(DROPFILES);

    // If we're compiling for Unicode, set the Unicode flag in the struct to
    // indicate it contains Unicode strings.
#ifdef _UNICODE
    pDrop->fWide = TRUE;
#endif;

    // Copy all the filenames into memory after the end of the DROPFILES struct.
    pos = lsDraggedFiles.GetHeadPosition();
    pszBuff = (TCHAR*) (LPBYTE(pDrop) + sizeof(DROPFILES));

    while ( pos )
    {
        lstrcpy ( pszBuff, (LPCTSTR) lsDraggedFiles.GetNext ( pos ) );
        pszBuff = 1 + _tcschr ( pszBuff, '\0' );
    }

    GlobalUnlock ( hgDrop );

    // Put the data in the data source.
    datasrc.CacheGlobalData ( CF_HDROP, hgDrop, &etc );

    // Add in our own custom data, so we know that the drag originated from our
    // window.  CMyDropTarget::DragEnter() checks for this custom format, and
    // doesn't allow the drop if it's present.  This is how we prevent the user
    // from dragging and then dropping in our own window.
    // The data will just be a dummy bool.
    HGLOBAL hgBool;

    hgBool = GlobalAlloc ( GHND | GMEM_SHARE, sizeof(bool) );

    if ( NULL == hgBool )
    {
        GlobalFree ( hgDrop );
        return;
    }

    // Put the data in the data source.
    etc.cfFormat = m_DropID;
    datasrc.CacheGlobalData ( m_DropID, hgBool, &etc );

    // Start the drag 'n' drop!
    DROPEFFECT dwEffect = datasrc.DoDragDrop ( DROPEFFECT_COPY | DROPEFFECT_MOVE );

    // If the DnD completed OK, we remove all of the dragged items from our
    // list.
    switch ( dwEffect )
    {
    case DROPEFFECT_COPY:
    case DROPEFFECT_MOVE:
    {
        // the copy completed successfully
        // do whatever we need to do here
        TRACE0( "DND from playlist completed successfully. The data has a new owner.\n" );
    }
    break;

    case DROPEFFECT_NONE:
    {
        // This needs special handling, because on NT, DROPEFFECT_NONE
        // is returned for move operations, instead of DROPEFFECT_MOVE.
        // See Q182219 for the details.
        // So if we're on NT, we check each selected item, and if the
        // file no longer exists, it was moved successfully and we can
        // remove it from the list.
        if ( m_IsWinNT )
        {
            // the copy completed successfully
            // on a windows nt machine.
            // do whatever we need to do here

            bool bDeletedAnything = false;
            if ( ! bDeletedAnything )
            {
                // The DnD operation wasn't accepted, or was canceled, so we
                // should call GlobalFree() to clean up.
                GlobalFree ( hgDrop );
                GlobalFree ( hgBool );

                TRACE0( "DND had a problem. We had to manually free the data.\n" );
            }
        }

        // not windows NT
        else
        {
            // We're on 9x, and a return of DROPEFFECT_NONE always means
            // that the DnD operation was aborted.  We need to free the
            // allocated memory.
            GlobalFree ( hgDrop );
            GlobalFree ( hgBool );

            TRACE0( "DND had a problem. We had to manually free the data.\n" );
        }
    }

    break;
    }
}