/***************************************************************************** * SIC_IconAppend [internal] * * NOTES * appends an icon pair to the end of the cache */ static INT SIC_IconAppend (LPCWSTR sSourceFile, INT dwSourceIndex, HICON hSmallIcon, HICON hBigIcon, DWORD dwFlags) { LPSIC_ENTRY lpsice; INT ret, index, index1, indexDPA; WCHAR path[MAX_PATH]; TRACE("%s %i %p %p\n", debugstr_w(sSourceFile), dwSourceIndex, hSmallIcon ,hBigIcon); lpsice = (LPSIC_ENTRY) SHAlloc (sizeof (SIC_ENTRY)); GetFullPathNameW(sSourceFile, MAX_PATH, path, NULL); lpsice->sSourceFile = (LPWSTR)HeapAlloc( GetProcessHeap(), 0, (wcslen(path)+1)*sizeof(WCHAR) ); wcscpy( lpsice->sSourceFile, path ); lpsice->dwSourceIndex = dwSourceIndex; lpsice->dwFlags = dwFlags; EnterCriticalSection(&SHELL32_SicCS); indexDPA = DPA_Search (sic_hdpa, lpsice, 0, SIC_CompareEntries, 0, DPAS_SORTED|DPAS_INSERTAFTER); indexDPA = DPA_InsertPtr(sic_hdpa, indexDPA, lpsice); if ( -1 == indexDPA ) { ret = INVALID_INDEX; goto leave; } index = ImageList_AddIcon (ShellSmallIconList, hSmallIcon); index1= ImageList_AddIcon (ShellBigIconList, hBigIcon); /* Something went wrong when allocating a new image in the list. Abort. */ if((index == -1) || (index1 == -1)) { WARN("Something went wrong when adding the icon to the list: small - 0x%x, big - 0x%x.\n", index, index1); if(index != -1) ImageList_Remove(ShellSmallIconList, index); if(index1 != -1) ImageList_Remove(ShellBigIconList, index1); ret = INVALID_INDEX; goto leave; } if (index!=index1) { FIXME("iconlists out of sync 0x%x 0x%x\n", index, index1); /* What to do ???? */ } lpsice->dwListIndex = index; ret = lpsice->dwListIndex; leave: if(ret == INVALID_INDEX) { if(indexDPA != -1) DPA_DeletePtr(sic_hdpa, indexDPA); HeapFree(GetProcessHeap(), 0, lpsice->sSourceFile); SHFree(lpsice); } LeaveCriticalSection(&SHELL32_SicCS); return ret; }
/************************************************************************** * DPA_Merge [COMCTL32.11] * * Merge two dynamic pointers arrays. * * PARAMS * hdpa1 [I] handle to a dynamic pointer array * hdpa2 [I] handle to a dynamic pointer array * dwFlags [I] flags * pfnCompare [I] pointer to sort function * pfnMerge [I] pointer to merge function * lParam [I] application specific value * * RETURNS * Success: TRUE * Failure: FALSE * * NOTES * No more information available yet! */ BOOL WINAPI DPA_Merge (HDPA hdpa1, HDPA hdpa2, DWORD dwFlags, PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, LPARAM lParam) { INT nCount; LPVOID *pWork1, *pWork2; INT nResult, i; INT nIndex; TRACE("%p %p %08x %p %p %08lx)\n", hdpa1, hdpa2, dwFlags, pfnCompare, pfnMerge, lParam); if (IsBadWritePtr (hdpa1, sizeof(*hdpa1))) return FALSE; if (IsBadWritePtr (hdpa2, sizeof(*hdpa2))) return FALSE; if (IsBadCodePtr ((FARPROC)pfnCompare)) return FALSE; if (IsBadCodePtr ((FARPROC)pfnMerge)) return FALSE; if (!(dwFlags & DPAM_SORTED)) { TRACE("sorting dpa's!\n"); if (hdpa1->nItemCount > 0) DPA_Sort (hdpa1, pfnCompare, lParam); TRACE ("dpa 1 sorted!\n"); if (hdpa2->nItemCount > 0) DPA_Sort (hdpa2, pfnCompare, lParam); TRACE ("dpa 2 sorted!\n"); } if (hdpa2->nItemCount < 1) return TRUE; TRACE("hdpa1->nItemCount=%d hdpa2->nItemCount=%d\n", hdpa1->nItemCount, hdpa2->nItemCount); /* working but untrusted implementation */ pWork1 = &(hdpa1->ptrs[hdpa1->nItemCount - 1]); pWork2 = &(hdpa2->ptrs[hdpa2->nItemCount - 1]); nIndex = hdpa1->nItemCount - 1; nCount = hdpa2->nItemCount - 1; do { if (nIndex < 0) { if ((nCount >= 0) && (dwFlags & DPAM_UNION)) { /* Now insert the remaining new items into DPA 1 */ TRACE("%d items to be inserted at start of DPA 1\n", nCount+1); for (i=nCount; i>=0; i--) { PVOID ptr; ptr = (pfnMerge)(DPAMM_INSERT, *pWork2, NULL, lParam); if (!ptr) return FALSE; DPA_InsertPtr (hdpa1, 0, ptr); pWork2--; } } break; } nResult = (pfnCompare)(*pWork1, *pWork2, lParam); TRACE("compare result=%d, dpa1.cnt=%d, dpa2.cnt=%d\n", nResult, nIndex, nCount); if (nResult == 0) { PVOID ptr; ptr = (pfnMerge)(DPAMM_MERGE, *pWork1, *pWork2, lParam); if (!ptr) return FALSE; nCount--; pWork2--; *pWork1 = ptr; nIndex--; pWork1--; } else if (nResult > 0) { /* item in DPA 1 missing from DPA 2 */ if (dwFlags & DPAM_INTERSECT) { /* Now delete the extra item in DPA1 */ PVOID ptr; ptr = DPA_DeletePtr (hdpa1, nIndex); (pfnMerge)(DPAMM_DELETE, ptr, NULL, lParam); } nIndex--; pWork1--; } else { /* new item in DPA 2 */ if (dwFlags & DPAM_UNION) { /* Now insert the new item in DPA 1 */ PVOID ptr; ptr = (pfnMerge)(DPAMM_INSERT, *pWork2, NULL, lParam); if (!ptr) return FALSE; DPA_InsertPtr (hdpa1, nIndex+1, ptr); } nCount--; pWork2--; } } while (nCount >= 0); return TRUE; }