Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenexticon.c
Go to the documentation of this file.
00001 /* 00002 * icon extracting 00003 * 00004 * taken and slightly changed from shell 00005 * this should replace the icon extraction code in shell32 and shell16 once 00006 * it needs a serious test for compliance with the native API 00007 * 00008 * Copyright 2000 Juergen Schmied 00009 * 00010 * This library is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU Lesser General Public 00012 * License as published by the Free Software Foundation; either 00013 * version 2.1 of the License, or (at your option) any later version. 00014 * 00015 * This library is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 * Lesser General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU Lesser General Public 00021 * License along with this library; if not, write to the Free Software 00022 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00023 */ 00024 00025 #include <user32.h> 00026 00027 #include <wine/debug.h> 00028 00029 /* Start of Hack section */ 00030 00031 WINE_DEFAULT_DEBUG_CHANNEL(icon); 00032 00033 #include "pshpack1.h" 00034 00035 typedef struct 00036 { 00037 BYTE bWidth; /* Width, in pixels, of the image */ 00038 BYTE bHeight; /* Height, in pixels, of the image */ 00039 BYTE bColorCount; /* Number of colors in image (0 if >=8bpp) */ 00040 BYTE bReserved; /* Reserved ( must be 0) */ 00041 WORD wPlanes; /* Color Planes */ 00042 WORD wBitCount; /* Bits per pixel */ 00043 DWORD dwBytesInRes; /* How many bytes in this resource? */ 00044 DWORD dwImageOffset; /* Where in the file is this image? */ 00045 } icoICONDIRENTRY, *LPicoICONDIRENTRY; 00046 00047 typedef struct 00048 { 00049 WORD idReserved; /* Reserved (must be 0) */ 00050 WORD idType; /* Resource Type (RES_ICON or RES_CURSOR) */ 00051 WORD idCount; /* How many images */ 00052 icoICONDIRENTRY idEntries[1]; /* An entry for each image (idCount of 'em) */ 00053 } icoICONDIR, *LPicoICONDIR; 00054 00055 #include "poppack.h" 00056 00057 #if 0 00058 static void dumpIcoDirEnty ( LPicoICONDIRENTRY entry ) 00059 { 00060 TRACE("width = 0x%08x height = 0x%08x\n", entry->bWidth, entry->bHeight); 00061 TRACE("colors = 0x%08x planes = 0x%08x\n", entry->bColorCount, entry->wPlanes); 00062 TRACE("bitcount = 0x%08x bytesinres = 0x%08lx offset = 0x%08lx\n", 00063 entry->wBitCount, entry->dwBytesInRes, entry->dwImageOffset); 00064 } 00065 static void dumpIcoDir ( LPicoICONDIR entry ) 00066 { 00067 TRACE("type = 0x%08x count = 0x%08x\n", entry->idType, entry->idCount); 00068 } 00069 #endif 00070 00071 /********************************************************************** 00072 * find_entry_by_id 00073 * 00074 * Find an entry by id in a resource directory 00075 * Copied from loader/pe_resource.c (FIXME: should use exported resource functions) 00076 */ 00077 static const IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( const IMAGE_RESOURCE_DIRECTORY *dir, 00078 WORD id, const void *root ) 00079 { 00080 const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry; 00081 int min, max, pos; 00082 00083 entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1); 00084 min = dir->NumberOfNamedEntries; 00085 max = min + dir->NumberOfIdEntries - 1; 00086 while (min <= max) 00087 { 00088 pos = (min + max) / 2; 00089 if (entry[pos].Id == id) 00090 return (const IMAGE_RESOURCE_DIRECTORY *)((const char *)root + entry[pos].OffsetToDirectory); 00091 if (entry[pos].Id > id) max = pos - 1; 00092 else min = pos + 1; 00093 } 00094 return NULL; 00095 } 00096 00097 /********************************************************************** 00098 * find_entry_default 00099 * 00100 * Find a default entry in a resource directory 00101 * Copied from loader/pe_resource.c (FIXME: should use exported resource functions) 00102 */ 00103 static const IMAGE_RESOURCE_DIRECTORY *find_entry_default( const IMAGE_RESOURCE_DIRECTORY *dir, 00104 const void *root ) 00105 { 00106 const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry; 00107 entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1); 00108 return (const IMAGE_RESOURCE_DIRECTORY *)((const char *)root + entry->OffsetToDirectory); 00109 } 00110 00111 /************************************************************************* 00112 * USER32_GetResourceTable 00113 */ 00114 static DWORD USER32_GetResourceTable(LPBYTE peimage,DWORD pesize,LPBYTE *retptr) 00115 { 00116 IMAGE_DOS_HEADER * mz_header; 00117 00118 TRACE("%p %p\n", peimage, retptr); 00119 00120 *retptr = NULL; 00121 00122 mz_header = (IMAGE_DOS_HEADER*) peimage; 00123 00124 if (mz_header->e_magic != IMAGE_DOS_SIGNATURE) 00125 { 00126 if (mz_header->e_cblp == 1) /* .ICO file ? */ 00127 { 00128 *retptr = (LPBYTE)-1; /* ICONHEADER.idType, must be 1 */ 00129 return 1; 00130 } 00131 else 00132 return 0; /* failed */ 00133 } 00134 if (mz_header->e_lfanew >= pesize) { 00135 return 0; /* failed, happens with PKZIP DOS Exes for instance. */ 00136 } 00137 if (*((DWORD*)(peimage + mz_header->e_lfanew)) == IMAGE_NT_SIGNATURE ) 00138 return IMAGE_NT_SIGNATURE; 00139 #if 0 00140 if (*((WORD*)(peimage + mz_header->e_lfanew)) == IMAGE_OS2_SIGNATURE ) 00141 { 00142 IMAGE_OS2_HEADER * ne_header; 00143 00144 ne_header = (IMAGE_OS2_HEADER*)(peimage + mz_header->e_lfanew); 00145 00146 if (ne_header->ne_magic != IMAGE_OS2_SIGNATURE) 00147 return 0; 00148 00149 if( (ne_header->ne_restab - ne_header->ne_rsrctab) <= sizeof(NE_TYPEINFO) ) 00150 *retptr = (LPBYTE)-1; 00151 else 00152 *retptr = peimage + mz_header->e_lfanew + ne_header->ne_rsrctab; 00153 00154 return IMAGE_OS2_SIGNATURE; 00155 } 00156 #endif 00157 return 0; /* failed */ 00158 } 00159 #if 0 00160 /************************************************************************* 00161 * USER32_LoadResource 00162 */ 00163 static BYTE * USER32_LoadResource( LPBYTE peimage, NE_NAMEINFO* pNInfo, WORD sizeShift, ULONG *uSize) 00164 { 00165 TRACE("%p %p 0x%08x\n", peimage, pNInfo, sizeShift); 00166 00167 *uSize = (DWORD)pNInfo->length << sizeShift; 00168 return peimage + ((DWORD)pNInfo->offset << sizeShift); 00169 } 00170 00171 /************************************************************************* 00172 * ICO_LoadIcon 00173 */ 00174 static BYTE * ICO_LoadIcon( LPBYTE peimage, LPicoICONDIRENTRY lpiIDE, ULONG *uSize) 00175 { 00176 TRACE("%p %p\n", peimage, lpiIDE); 00177 00178 *uSize = lpiIDE->dwBytesInRes; 00179 return peimage + lpiIDE->dwImageOffset; 00180 } 00181 00182 /************************************************************************* 00183 * ICO_GetIconDirectory 00184 * 00185 * Reads .ico file and build phony ICONDIR struct 00186 */ 00187 #define HEADER_SIZE (sizeof(CURSORICONDIR) - sizeof (CURSORICONDIRENTRY)) 00188 #define HEADER_SIZE_FILE (sizeof(icoICONDIR) - sizeof (icoICONDIRENTRY)) 00189 00190 static BYTE * ICO_GetIconDirectory( LPBYTE peimage, LPicoICONDIR* lplpiID, ULONG *uSize ) 00191 { 00192 CURSORICONDIR * lpcid; /* icon resource in resource-dir format */ 00193 CURSORICONDIR * lpID; /* icon resource in resource format */ 00194 int i; 00195 00196 TRACE("%p %p\n", peimage, lplpiID); 00197 00198 lpcid = (CURSORICONDIR*)peimage; 00199 00200 if( lpcid->idReserved || (lpcid->idType != 1) || (!lpcid->idCount) ) 00201 return 0; 00202 00203 /* allocate the phony ICONDIR structure */ 00204 *uSize = lpcid->idCount * sizeof(CURSORICONDIRENTRY) + HEADER_SIZE; 00205 if( (lpID = HeapAlloc(GetProcessHeap(),0, *uSize) )) 00206 { 00207 /* copy the header */ 00208 lpID->idReserved = lpcid->idReserved; 00209 lpID->idType = lpcid->idType; 00210 lpID->idCount = lpcid->idCount; 00211 00212 /* copy the entries */ 00213 for( i=0; i < lpcid->idCount; i++ ) 00214 { 00215 memcpy(&lpID->idEntries[i], &lpcid->idEntries[i], sizeof(CURSORICONDIRENTRY) - 2); 00216 lpID->idEntries[i].wResId = i; 00217 } 00218 00219 *lplpiID = (LPicoICONDIR)peimage; 00220 return (BYTE *)lpID; 00221 } 00222 return 0; 00223 } 00224 #endif 00225 /************************************************************************* 00226 * ICO_ExtractIconExW [internal] 00227 * 00228 * NOTES 00229 * nIcons = 0: returns number of Icons in file 00230 * 00231 * returns 00232 * invalid file: -1 00233 * failure:0; 00234 * success: number of icons in file (nIcons = 0) or nr of icons retrieved 00235 */ 00236 static UINT ICO_ExtractIconExW( 00237 LPCWSTR lpszExeFileName, 00238 HICON * RetPtr, 00239 INT nIconIndex, 00240 UINT nIcons, 00241 UINT cxDesired, 00242 UINT cyDesired, 00243 UINT *pIconId, 00244 UINT flags) 00245 { 00246 UINT ret = 0; 00247 UINT cx1, cx2, cy1, cy2; 00248 LPBYTE pData; 00249 DWORD sig; 00250 HANDLE hFile; 00251 UINT16 iconDirCount = 0; //,iconCount = 0; 00252 LPBYTE peimage; 00253 HANDLE fmapping; 00254 DWORD fsizeh,fsizel; 00255 WCHAR szExePath[MAX_PATH]; 00256 DWORD dwSearchReturn; 00257 00258 TRACE("%s, %d, %d %p 0x%08x\n", debugstr_w(lpszExeFileName), nIconIndex, nIcons, pIconId, flags); 00259 00260 dwSearchReturn = SearchPathW(NULL, lpszExeFileName, NULL, sizeof(szExePath) / sizeof(szExePath[0]), szExePath, NULL); 00261 if ((dwSearchReturn == 0) || (dwSearchReturn > sizeof(szExePath) / sizeof(szExePath[0]))) 00262 { 00263 WARN("File %s not found or path too long\n", debugstr_w(lpszExeFileName)); 00264 return -1; 00265 } 00266 00267 hFile = CreateFileW(szExePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 00268 if (hFile == INVALID_HANDLE_VALUE) return ret; 00269 fsizel = GetFileSize(hFile,&fsizeh); 00270 00271 /* Map the file */ 00272 fmapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL); 00273 CloseHandle(hFile); 00274 if (!fmapping) 00275 { 00276 WARN("CreateFileMapping error %ld\n", GetLastError() ); 00277 return 0xFFFFFFFF; 00278 } 00279 00280 if (!(peimage = MapViewOfFile(fmapping, FILE_MAP_READ, 0, 0, 0))) 00281 { 00282 WARN("MapViewOfFile error %ld\n", GetLastError() ); 00283 CloseHandle(fmapping); 00284 return 0xFFFFFFFF; 00285 } 00286 CloseHandle(fmapping); 00287 00288 cx1 = LOWORD(cxDesired); 00289 cx2 = HIWORD(cxDesired); 00290 cy1 = LOWORD(cyDesired); 00291 cy2 = HIWORD(cyDesired); 00292 00293 if (pIconId) /* Invalidate first icon identifier */ 00294 *pIconId = 0xFFFFFFFF; 00295 00296 if (!pIconId) /* if no icon identifier array present use the icon handle array as intermediate storage */ 00297 pIconId = (UINT*)RetPtr; 00298 00299 sig = USER32_GetResourceTable(peimage, fsizel, &pData); 00300 00301 /* ico file or NE exe/dll*/ 00302 #if 0 00303 if (sig==IMAGE_OS2_SIGNATURE || sig==1) /* .ICO file */ 00304 { 00305 BYTE *pCIDir = 0; 00306 NE_TYPEINFO *pTInfo = (NE_TYPEINFO*)(pData + 2); 00307 NE_NAMEINFO *pIconStorage = NULL; 00308 NE_NAMEINFO *pIconDir = NULL; 00309 LPicoICONDIR lpiID = NULL; 00310 00311 TRACE("-- OS2/icon Signature (0x%08lx)\n", sig); 00312 00313 if (pData == (BYTE*)-1) 00314 { 00315 pCIDir = ICO_GetIconDirectory(peimage, &lpiID, &uSize); /* check for .ICO file */ 00316 if (pCIDir) 00317 { 00318 iconDirCount = 1; iconCount = lpiID->idCount; 00319 TRACE("-- icon found %p 0x%08lx 0x%08x 0x%08x\n", pCIDir, uSize, iconDirCount, iconCount); 00320 } 00321 } 00322 else while (pTInfo->type_id && !(pIconStorage && pIconDir)) 00323 { 00324 if (pTInfo->type_id == NE_RSCTYPE_GROUP_ICON) /* find icon directory and icon repository */ 00325 { 00326 iconDirCount = pTInfo->count; 00327 pIconDir = ((NE_NAMEINFO*)(pTInfo + 1)); 00328 TRACE("\tfound directory - %i icon families\n", iconDirCount); 00329 } 00330 if (pTInfo->type_id == NE_RSCTYPE_ICON) 00331 { 00332 iconCount = pTInfo->count; 00333 pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1)); 00334 TRACE("\ttotal icons - %i\n", iconCount); 00335 } 00336 pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO)); 00337 } 00338 00339 if ((pIconStorage && pIconDir) || lpiID) /* load resources and create icons */ 00340 { 00341 if (nIcons == 0) 00342 { 00343 ret = iconDirCount; 00344 if (lpiID && pCIDir) /* *.ico file, deallocate heap pointer*/ 00345 HeapFree(GetProcessHeap(), 0, pCIDir); 00346 } 00347 else if (nIconIndex < iconDirCount) 00348 { 00349 UINT16 i, icon; 00350 if (nIcons > iconDirCount - nIconIndex) 00351 nIcons = iconDirCount - nIconIndex; 00352 00353 for (i = 0; i < nIcons; i++) 00354 { 00355 /* .ICO files have only one icon directory */ 00356 if (lpiID == NULL) /* not *.ico */ 00357 pCIDir = USER32_LoadResource(peimage, pIconDir + i + nIconIndex, *(WORD*)pData, &uSize); 00358 pIconId[i] = LookupIconIdFromDirectoryEx(pCIDir, TRUE, (i & 1) ? cx2 : cx1, (i & 1) ? cy2 : cy1, flags); 00359 } 00360 if (lpiID && pCIDir) /* *.ico file, deallocate heap pointer*/ 00361 HeapFree(GetProcessHeap(), 0, pCIDir); 00362 00363 for (icon = 0; icon < nIcons; icon++) 00364 { 00365 pCIDir = NULL; 00366 if (lpiID) 00367 pCIDir = ICO_LoadIcon(peimage, lpiID->idEntries + (int)pIconId[icon], &uSize); 00368 else 00369 for (i = 0; i < iconCount; i++) 00370 if (pIconStorage[i].id == ((int)pIconId[icon] | 0x8000) ) 00371 pCIDir = USER32_LoadResource(peimage, pIconStorage + i, *(WORD*)pData, &uSize); 00372 00373 if (pCIDir) 00374 RetPtr[icon] = (HICON)CreateIconFromResourceEx(pCIDir, uSize, TRUE, 0x00030000, 00375 (icon & 1) ? cx2 : cx1, (icon & 1) ? cy2 : cy1, flags); 00376 else 00377 RetPtr[icon] = 0; 00378 } 00379 ret = icon; /* return number of retrieved icons */ 00380 } 00381 } 00382 } 00383 /* end ico file */ 00384 00385 /* exe/dll */ 00386 else if( sig == IMAGE_NT_SIGNATURE ) 00387 #endif 00388 if( sig == IMAGE_NT_SIGNATURE ) 00389 { 00390 LPBYTE idata,igdata; 00391 PIMAGE_DOS_HEADER dheader; 00392 PIMAGE_NT_HEADERS pe_header; 00393 PIMAGE_SECTION_HEADER pe_sections; 00394 const IMAGE_RESOURCE_DIRECTORY *rootresdir,*iconresdir,*icongroupresdir; 00395 const IMAGE_RESOURCE_DATA_ENTRY *idataent,*igdataent; 00396 const IMAGE_RESOURCE_DIRECTORY_ENTRY *xresent; 00397 UINT i, j; 00398 00399 dheader = (PIMAGE_DOS_HEADER)peimage; 00400 pe_header = (PIMAGE_NT_HEADERS)(peimage+dheader->e_lfanew); /* it is a pe header, USER32_GetResourceTable checked that */ 00401 pe_sections = (PIMAGE_SECTION_HEADER)(((char*)pe_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) 00402 + pe_header->FileHeader.SizeOfOptionalHeader); 00403 rootresdir = NULL; 00404 00405 /* search for the root resource directory */ 00406 for (i=0;i<pe_header->FileHeader.NumberOfSections;i++) 00407 { 00408 if (pe_sections[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) 00409 continue; 00410 if (fsizel < pe_sections[i].PointerToRawData+pe_sections[i].SizeOfRawData) { 00411 FIXME("File %s too short (section is at %ld bytes, real size is %ld)\n", 00412 debugstr_w(lpszExeFileName), 00413 pe_sections[i].PointerToRawData+pe_sections[i].SizeOfRawData, 00414 fsizel 00415 ); 00416 goto end; 00417 } 00418 /* FIXME: doesn't work when the resources are not in a separate section */ 00419 if (pe_sections[i].VirtualAddress == pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress) 00420 { 00421 rootresdir = (PIMAGE_RESOURCE_DIRECTORY)(peimage+pe_sections[i].PointerToRawData); 00422 break; 00423 } 00424 } 00425 00426 if (!rootresdir) 00427 { 00428 WARN("haven't found section for resource directory.\n"); 00429 goto end; /* failure */ 00430 } 00431 00432 /* search for the group icon directory */ 00433 if (!(icongroupresdir = find_entry_by_id(rootresdir, LOWORD(RT_GROUP_ICON), rootresdir))) 00434 { 00435 WARN("No Icongroupresourcedirectory!\n"); 00436 goto end; /* failure */ 00437 } 00438 iconDirCount = icongroupresdir->NumberOfNamedEntries + icongroupresdir->NumberOfIdEntries; 00439 00440 /* only number of icons requested */ 00441 if( !pIconId ) 00442 { 00443 ret = iconDirCount; 00444 goto end; /* success */ 00445 } 00446 00447 if( nIconIndex < 0 ) 00448 { 00449 /* search resource id */ 00450 int n = 0; 00451 int iId = abs(nIconIndex); 00452 const IMAGE_RESOURCE_DIRECTORY_ENTRY* xprdeTmp = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(icongroupresdir+1); 00453 00454 while(n<iconDirCount && xprdeTmp) 00455 { 00456 if(xprdeTmp->Id == iId) 00457 { 00458 nIconIndex = n; 00459 break; 00460 } 00461 n++; 00462 xprdeTmp++; 00463 } 00464 if (nIconIndex < 0) 00465 { 00466 WARN("resource id %d not found\n", iId); 00467 goto end; /* failure */ 00468 } 00469 } 00470 else 00471 { 00472 /* check nIconIndex to be in range */ 00473 if (nIconIndex >= iconDirCount) 00474 { 00475 WARN("nIconIndex %d is larger than iconDirCount %d\n",nIconIndex,iconDirCount); 00476 goto end; /* failure */ 00477 } 00478 } 00479 00480 /* assure we don't get too much */ 00481 if( nIcons > iconDirCount - nIconIndex ) 00482 nIcons = iconDirCount - nIconIndex; 00483 00484 /* starting from specified index */ 00485 xresent = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(icongroupresdir+1) + nIconIndex; 00486 00487 for (i=0; i < nIcons; i++,xresent++) 00488 { 00489 const IMAGE_RESOURCE_DIRECTORY *resdir; 00490 00491 /* go down this resource entry, name */ 00492 resdir = (const IMAGE_RESOURCE_DIRECTORY*)((const char *)rootresdir+(xresent->OffsetToDirectory)); 00493 00494 /* default language (0) */ 00495 resdir = find_entry_default(resdir,rootresdir); 00496 igdataent = (const IMAGE_RESOURCE_DATA_ENTRY*)resdir; 00497 00498 /* lookup address in mapped image for virtual address */ 00499 igdata = NULL; 00500 00501 for (j=0;j<pe_header->FileHeader.NumberOfSections;j++) 00502 { 00503 if (igdataent->OffsetToData < pe_sections[j].VirtualAddress) 00504 continue; 00505 if (igdataent->OffsetToData+igdataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData) 00506 continue; 00507 00508 if (igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData+igdataent->Size > fsizel) { 00509 FIXME("overflow in PE lookup (%s has len %ld, have offset %ld), short file?\n", debugstr_w(lpszExeFileName), fsizel, 00510 igdataent->OffsetToData - pe_sections[j].VirtualAddress + pe_sections[j].PointerToRawData + igdataent->Size); 00511 goto end; /* failure */ 00512 } 00513 igdata = peimage+(igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData); 00514 } 00515 00516 if (!igdata) 00517 { 00518 FIXME("no matching real address for icongroup!\n"); 00519 goto end; /* failure */ 00520 } 00521 pIconId[i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx1, cy1, flags); 00522 if (cx2 && cy2) pIconId[++i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx2, cy2, flags); 00523 } 00524 00525 if (!(iconresdir=find_entry_by_id(rootresdir,LOWORD(RT_ICON),rootresdir))) 00526 { 00527 WARN("No Iconresourcedirectory!\n"); 00528 goto end; /* failure */ 00529 } 00530 00531 for (i=0; i<nIcons; i++) 00532 { 00533 const IMAGE_RESOURCE_DIRECTORY *xresdir; 00534 xresdir = find_entry_by_id(iconresdir, LOWORD(pIconId[i]), rootresdir); 00535 if (!xresdir) 00536 { 00537 WARN("icon entry %d not found\n", LOWORD(pIconId[i])); 00538 RetPtr[i]=0; 00539 continue; 00540 } 00541 xresdir = find_entry_default(xresdir, rootresdir); 00542 if (!xresdir) 00543 { 00544 WARN("icon entry %d not found\n", LOWORD(pIconId[i])); 00545 RetPtr[i]=0; 00546 continue; 00547 } 00548 idataent = (const IMAGE_RESOURCE_DATA_ENTRY*)xresdir; 00549 idata = NULL; 00550 00551 /* map virtual to address in image */ 00552 for (j=0;j<pe_header->FileHeader.NumberOfSections;j++) 00553 { 00554 if (idataent->OffsetToData < pe_sections[j].VirtualAddress) 00555 continue; 00556 if (idataent->OffsetToData+idataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData) 00557 continue; 00558 idata = peimage+(idataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData); 00559 } 00560 if (!idata) 00561 { 00562 WARN("no matching real address found for icondata!\n"); 00563 RetPtr[i]=0; 00564 continue; 00565 } 00566 RetPtr[i] = CreateIconFromResourceEx(idata, idataent->Size, TRUE, 0x00030000, cx1, cy1, flags); 00567 if (cx2 && cy2) 00568 RetPtr[++i] = CreateIconFromResourceEx(idata, idataent->Size, TRUE, 0x00030000, cx2, cy2, flags); 00569 } 00570 ret = i; /* return number of retrieved icons */ 00571 } /* if(sig == IMAGE_NT_SIGNATURE) */ 00572 00573 end: 00574 UnmapViewOfFile(peimage); /* success */ 00575 return ret; 00576 } 00577 00578 /*********************************************************************** 00579 * PrivateExtractIconsW [USER32.@] 00580 * 00581 * NOTES 00582 * If HIWORD(sizeX) && HIWORD(sizeY) 2 * ((nIcons + 1) MOD 2) icons are 00583 * returned, with the LOWORD size icon first and the HIWORD size icon 00584 * second. 00585 * Also the Windows equivalent does extract icons in a strange way if 00586 * nIndex is negative. Our implementation treats a negative nIndex as 00587 * looking for that resource identifier for the first icon to retrieve. 00588 * 00589 * FIXME: 00590 * should also support 16 bit EXE + DLLs, cursor and animated cursor as 00591 * well as bitmap files. 00592 */ 00593 00594 UINT WINAPI PrivateExtractIconsW ( 00595 LPCWSTR lpwstrFile, 00596 int nIndex, 00597 int sizeX, 00598 int sizeY, 00599 HICON * phicon, /* [out] pointer to array of nIcons HICON handles */ 00600 UINT* pIconId, /* [out] pointer to array of nIcons icon identifiers or NULL */ 00601 UINT nIcons, /* [in] number of icons to retrieve */ 00602 UINT flags ) /* [in] LR_* flags used by LoadImage */ 00603 { 00604 TRACE("%s %d %dx%d %p %p %d 0x%08x\n", 00605 debugstr_w(lpwstrFile), nIndex, sizeX, sizeY, phicon, pIconId, nIcons, flags); 00606 00607 if ((nIcons & 1) && HIWORD(sizeX) && HIWORD(sizeY)) 00608 { 00609 WARN("Uneven number %d of icons requested for small and large icons!\n", nIcons); 00610 } 00611 return ICO_ExtractIconExW(lpwstrFile, phicon, nIndex, nIcons, sizeX, sizeY, pIconId, flags); 00612 } 00613 00614 /*********************************************************************** 00615 * PrivateExtractIconsA [USER32.@] 00616 */ 00617 00618 UINT WINAPI PrivateExtractIconsA ( 00619 LPCSTR lpstrFile, 00620 int nIndex, 00621 int sizeX, 00622 int sizeY, 00623 HICON * phicon, /* [out] pointer to array of nIcons HICON handles */ 00624 UINT* piconid, /* [out] pointer to array of nIcons icon identifiers or NULL */ 00625 UINT nIcons, /* [in] number of icons to retrieve */ 00626 UINT flags ) /* [in] LR_* flags used by LoadImage */ 00627 { 00628 UINT ret; 00629 INT len = MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, NULL, 0); 00630 LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 00631 if (lpwstrFile == NULL) 00632 return 0; 00633 00634 MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, lpwstrFile, len); 00635 ret = PrivateExtractIconsW(lpwstrFile, nIndex, sizeX, sizeY, phicon, piconid, nIcons, flags); 00636 00637 HeapFree(GetProcessHeap(), 0, lpwstrFile); 00638 return ret; 00639 } 00640 00641 /*********************************************************************** 00642 * PrivateExtractIconExW [USER32.@] 00643 * NOTES 00644 * if nIndex == -1 it returns the number of icons in any case !!! 00645 */ 00646 UINT WINAPI PrivateExtractIconExW ( 00647 LPCWSTR lpwstrFile, 00648 int nIndex, 00649 HICON * phIconLarge, 00650 HICON * phIconSmall, 00651 UINT nIcons ) 00652 { 00653 DWORD cyicon, cysmicon, cxicon, cxsmicon; 00654 UINT ret = 0; 00655 00656 TRACE("%s %d %p %p %d\n", 00657 debugstr_w(lpwstrFile),nIndex,phIconLarge, phIconSmall, nIcons); 00658 00659 if (nIndex == -1) 00660 /* get the number of icons */ 00661 return ICO_ExtractIconExW(lpwstrFile, NULL, 0, 0, 0, 0, NULL, LR_DEFAULTCOLOR); 00662 00663 if (nIcons == 1 && phIconSmall && phIconLarge) 00664 { 00665 HICON hIcon[2]; 00666 cxicon = GetSystemMetrics(SM_CXICON); 00667 cyicon = GetSystemMetrics(SM_CYICON); 00668 cxsmicon = GetSystemMetrics(SM_CXSMICON); 00669 cysmicon = GetSystemMetrics(SM_CYSMICON); 00670 00671 ret = ICO_ExtractIconExW(lpwstrFile, hIcon, nIndex, 2, cxicon | (cxsmicon<<16), 00672 cyicon | (cysmicon<<16), NULL, LR_DEFAULTCOLOR); 00673 *phIconLarge = hIcon[0]; 00674 *phIconSmall = hIcon[1]; 00675 return ret; 00676 } 00677 00678 if (phIconSmall) 00679 { 00680 /* extract n small icons */ 00681 cxsmicon = GetSystemMetrics(SM_CXSMICON); 00682 cysmicon = GetSystemMetrics(SM_CYSMICON); 00683 ret = ICO_ExtractIconExW(lpwstrFile, phIconSmall, nIndex, nIcons, cxsmicon, 00684 cysmicon, NULL, LR_DEFAULTCOLOR); 00685 } 00686 if (phIconLarge) 00687 { 00688 /* extract n large icons */ 00689 cxicon = GetSystemMetrics(SM_CXICON); 00690 cyicon = GetSystemMetrics(SM_CYICON); 00691 ret = ICO_ExtractIconExW(lpwstrFile, phIconLarge, nIndex, nIcons, cxicon, 00692 cyicon, NULL, LR_DEFAULTCOLOR); 00693 } 00694 return ret; 00695 } 00696 00697 /*********************************************************************** 00698 * PrivateExtractIconExA [USER32.@] 00699 */ 00700 UINT WINAPI PrivateExtractIconExA ( 00701 LPCSTR lpstrFile, 00702 int nIndex, 00703 HICON * phIconLarge, 00704 HICON * phIconSmall, 00705 UINT nIcons ) 00706 { 00707 UINT ret; 00708 INT len = MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, NULL, 0); 00709 LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 00710 if (lpwstrFile == NULL) 00711 return 0; 00712 00713 TRACE("%s %d %p %p %d\n", lpstrFile, nIndex, phIconLarge, phIconSmall, nIcons); 00714 00715 MultiByteToWideChar(CP_ACP, 0, lpstrFile, -1, lpwstrFile, len); 00716 ret = PrivateExtractIconExW(lpwstrFile, nIndex, phIconLarge, phIconSmall, nIcons); 00717 HeapFree(GetProcessHeap(), 0, lpwstrFile); 00718 return ret; 00719 } Generated on Fri May 25 2012 04:37:09 for ReactOS by
1.7.6.1
|