Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

acons.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: acons.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * This module contains code for dealing with animated icons/cursors. 00007 * 00008 * History: 00009 * 10-02-91 DarrinM Created. 00010 * 07-30-92 DarrinM Unicodized. 00011 * 11-28-94 JimA Moved to client from server. 00012 \***************************************************************************/ 00013 00014 #include "precomp.h" 00015 #pragma hdrstop 00016 00017 /* 00018 * Resource Directory format for IconEditor generated icon and cursor 00019 * (.ICO & .CUR) files. All fields are shared except xHotspot and yHotspot 00020 * which are only valid for cursors. 00021 */ 00022 typedef struct _ICONFILERESDIR { // ird 00023 BYTE bWidth; 00024 BYTE bHeight; 00025 BYTE bColorCount; 00026 BYTE bReserved; 00027 WORD xHotspot; 00028 WORD yHotspot; 00029 DWORD dwDIBSize; 00030 DWORD dwDIBOffset; 00031 } ICONFILERESDIR; 00032 00033 typedef struct _HOTSPOTREC { // hs 00034 WORD xHotspot; 00035 WORD yHotspot; 00036 } HOTSPOTREC; 00037 00038 PCURSORRESOURCE ReadIconGuts( 00039 IN PFILEINFO pfi, 00040 IN LPNEWHEADER pnhBase, 00041 IN int offResBase, 00042 OUT LPWSTR *prt, 00043 IN int cxDesired, 00044 IN int cyDesired, 00045 IN DWORD LR_flags); 00046 00047 BOOL ReadTag( 00048 IN PFILEINFO pfi, 00049 OUT PRTAG ptag); 00050 00051 BOOL ReadChunk( 00052 IN PFILEINFO pfi, 00053 IN PRTAG ptag, 00054 OUT PVOID pv); 00055 00056 BOOL SkipChunk( 00057 IN PFILEINFO pfi, 00058 IN PRTAG ptag); 00059 00060 HICON CreateAniIcon( 00061 LPCWSTR pszName, 00062 LPWSTR rt, 00063 int cicur, 00064 DWORD *aicur, 00065 int cpcur, 00066 HCURSOR *ahcur, 00067 JIF jifRate, 00068 PJIF ajifRate, 00069 BOOL fPublic); 00070 00071 HCURSOR ReadIconFromFileMap( 00072 IN PFILEINFO pfi, 00073 IN int cbSize, 00074 IN DWORD cxDesired, 00075 IN DWORD cyDesired, 00076 IN DWORD LR_flags); 00077 00078 HICON LoadAniIcon( 00079 IN PFILEINFO pfi, 00080 IN LPWSTR rt, 00081 IN DWORD cxDesired, 00082 IN DWORD cyDesired, 00083 IN DWORD LR_flags); 00084 00085 00086 00087 /***************************************************************************\ 00088 * LoadCursorFromFile (API) 00089 * 00090 * Called by SetSystemCursor. 00091 * 00092 * History: 00093 * 08-03-92 DarrinM Created. 00094 \***************************************************************************/ 00095 00096 HCURSOR WINAPI LoadCursorFromFileW( 00097 LPCWSTR pszFilename) 00098 { 00099 return(LoadImage(NULL, 00100 pszFilename, 00101 IMAGE_CURSOR, 00102 0, 00103 0, 00104 LR_DEFAULTSIZE | LR_LOADFROMFILE)); 00105 } 00106 00107 00108 00109 /***********************************************************************\ 00110 * LoadCursorFromFileA 00111 * 00112 * Returns: hCursor 00113 * 00114 * 10/9/1995 Created SanfordS 00115 \***********************************************************************/ 00116 00117 HCURSOR WINAPI LoadCursorFromFileA( 00118 LPCSTR pszFilename) 00119 { 00120 LPWSTR lpUniName; 00121 HCURSOR hcur; 00122 00123 if (pszFilename == NULL || 00124 !MBToWCS(pszFilename, -1, &lpUniName, -1, TRUE)) 00125 return (HANDLE)NULL; 00126 00127 hcur = LoadCursorFromFileW(lpUniName); 00128 00129 UserLocalFree(lpUniName); 00130 00131 return hcur; 00132 } 00133 00134 00135 00136 /***********************************************************************\ 00137 * ReadFilePtr 00138 * 00139 * Works like ReadFile but with pointers to a mapped file buffer. 00140 * 00141 * Returns: 00142 * 00143 * 11/16/1995 Created SanfordS 00144 \***********************************************************************/ 00145 BOOL ReadFilePtr( 00146 IN PFILEINFO pfi, 00147 OUT LPVOID *ppBuf, 00148 IN DWORD cb) 00149 { 00150 *ppBuf = pfi->pFilePtr; 00151 pfi->pFilePtr += cb; 00152 return (pfi->pFilePtr <= pfi->pFileEnd); 00153 } 00154 00155 00156 00157 /***********************************************************************\ 00158 * ReadFilePtrUnaligned 00159 * 00160 * Works like ReadFile but with pointers to a mapped file buffer. 00161 * 00162 * Returns: 00163 * 00164 * 11/16/1995 Created SanfordS 00165 \***********************************************************************/ 00166 BOOL ReadFilePtrUnaligned( 00167 IN PFILEINFO pfi, 00168 OUT VOID UNALIGNED **ppBuf, 00169 IN DWORD cb) 00170 { 00171 *ppBuf = pfi->pFilePtr; 00172 pfi->pFilePtr += cb; 00173 return (pfi->pFilePtr <= pfi->pFileEnd); 00174 } 00175 00176 00177 00178 /***********************************************************************\ 00179 * ReadFilePtrCopy 00180 * 00181 * Works even more like ReadFile in that is copies data to the given buffer. 00182 * 00183 * Returns: 00184 * 00185 * 11/16/1995 Created SanfordS 00186 \***********************************************************************/ 00187 BOOL ReadFilePtrCopy( 00188 IN PFILEINFO pfi, 00189 IN OUT LPVOID pBuf, 00190 IN DWORD cb) 00191 { 00192 if (pfi->pFilePtr + cb > pfi->pFileEnd) { 00193 return(FALSE); 00194 } 00195 RtlCopyMemory(pBuf, pfi->pFilePtr, cb); 00196 pfi->pFilePtr += cb; 00197 return TRUE; 00198 } 00199 00200 00201 00202 /***************************************************************************\ 00203 * ReadTag, ReadChunk, SkipChunk 00204 * 00205 * Some handy functions for reading RIFF files. 00206 * 00207 * History: 00208 * 10-02-91 DarrinM Created. 00209 * 03-25-93 Jonpa Changed to use RIFF format instead of ASDF 00210 \***************************************************************************/ 00211 BOOL ReadTag( 00212 IN PFILEINFO pfi, 00213 OUT PRTAG ptag) 00214 { 00215 ptag->ckID = ptag->ckSize = 0L; // in case we fail the read. 00216 00217 return(ReadFilePtrCopy(pfi, ptag, sizeof(RTAG))); 00218 } 00219 00220 00221 00222 BOOL ReadChunk( 00223 IN PFILEINFO pfi, 00224 IN PRTAG ptag, 00225 OUT PVOID pv) 00226 { 00227 if (!ReadFilePtrCopy(pfi, pv, ptag->ckSize)) 00228 return FALSE; 00229 00230 /* WORD align file pointer */ 00231 if( ptag->ckSize & 1 ) 00232 pfi->pFilePtr++; 00233 00234 00235 if (pfi->pFilePtr <= pfi->pFileEnd) { 00236 return TRUE; 00237 } else { 00238 RIPMSG0(RIP_WARNING, "ReadChunk: Advanced pointer past end of file map"); 00239 return FALSE; 00240 } 00241 } 00242 00243 00244 00245 BOOL SkipChunk( 00246 IN PFILEINFO pfi, 00247 IN PRTAG ptag) 00248 { 00249 /* 00250 * Round ptag->ckSize up to nearest word boundary 00251 * to maintain alignment 00252 */ 00253 pfi->pFilePtr += (ptag->ckSize + 1) & (~1); 00254 if (pfi->pFilePtr <= pfi->pFileEnd) { 00255 return TRUE; 00256 } else { 00257 RIPMSG0(RIP_WARNING, "SkipChunk: Advanced pointer past end of file map"); 00258 return FALSE; 00259 } 00260 } 00261 00262 00263 00264 /***************************************************************************\ 00265 * LoadCursorIconFromFileMap 00266 * 00267 * If pszName is one of the IDC_* values then we use WIN.INI to find a 00268 * custom cursor/icon. Otherwise, pszName points to a filename of a .ICO/.CUR 00269 * file to be loaded. If the file is an .ANI file containing a multiframe 00270 * animation then LoadAniIcon is called to create an ACON. Otherwise if 00271 * the file is an .ANI file containing just a single frame then it is loaded 00272 * and a normal CURSOR/ICON resource is created from it. 00273 * 00274 * 12-26-91 DarrinM Wrote it. 00275 * 03-17-93 JonPa Changed to use RIFF format for ani-cursors 00276 * 11/16/1995 SanfordS Added LR_flags support 00277 \***************************************************************************/ 00278 00279 HANDLE LoadCursorIconFromFileMap( 00280 IN PFILEINFO pfi, 00281 IN OUT LPWSTR *prt, 00282 IN DWORD cxDesired, 00283 IN DWORD cyDesired, 00284 IN DWORD LR_flags, 00285 OUT LPBOOL pfAni) 00286 { 00287 LPNEWHEADER pnh; 00288 int offResBase; 00289 00290 *pfAni = FALSE; 00291 offResBase = 0; 00292 00293 /* 00294 * Determine if this is an .ICO/.CUR file or an .ANI file. 00295 */ 00296 pnh = (LPNEWHEADER)pfi->pFileMap; 00297 if (*(LPDWORD)pnh == FOURCC_RIFF) { 00298 00299 RTAG tag; 00300 00301 /* 00302 * It's an ANICURSOR! 00303 * Seek back to beginning + 1 tag. 00304 */ 00305 pfi->pFilePtr = pfi->pFileMap + sizeof(tag); 00306 00307 /* check RIFF type for ACON */ 00308 if (*(LPDWORD)pfi->pFilePtr != FOURCC_ACON) { 00309 return NULL; 00310 } 00311 pfi->pFilePtr += sizeof(DWORD); 00312 if (pfi->pFilePtr > pfi->pFileEnd) { 00313 return NULL; 00314 } 00315 00316 /* 00317 * Ok, we have a ACON chunk. Find the first ICON chunk and set 00318 * things up so it looks we've just loaded the header of a normal 00319 * .CUR file, then fall into the .CUR bits handling code below. 00320 */ 00321 while (ReadTag(pfi, &tag)) { 00322 /* 00323 * Handle each chunk type. 00324 */ 00325 if (tag.ckID == FOURCC_anih) { 00326 00327 ANIHEADER anih; 00328 00329 if (!ReadChunk(pfi, &tag, &anih)) { 00330 return NULL; 00331 } 00332 00333 if (!(anih.fl & AF_ICON) || (anih.cFrames == 0)) { 00334 return NULL; 00335 } 00336 00337 // If this ACON has more than one frame then go ahead 00338 // and create an ACON, otherwise just use the first 00339 // frame to create a normal ICON/CURSOR. 00340 00341 if (anih.cFrames > 1) { 00342 00343 *pfAni = TRUE; 00344 *prt = RT_CURSOR; 00345 return(LoadAniIcon(pfi, 00346 RT_CURSOR, 00347 cxDesired, 00348 cyDesired, 00349 LR_flags)); 00350 } 00351 00352 } else if (tag.ckID == FOURCC_LIST) { 00353 LPDWORD pdwType = NULL; 00354 BOOL fOK = FALSE; 00355 /* 00356 * If this is the fram list, then get the first icon out of it 00357 */ 00358 00359 /* check LIST type for fram */ 00360 00361 if( tag.ckSize >= sizeof(DWORD) && 00362 (fOK = ReadFilePtr( pfi, 00363 &pdwType, 00364 sizeof(DWORD))) && 00365 *pdwType == FOURCC_fram) { 00366 00367 if (!ReadTag(pfi, &tag)) { 00368 return NULL; 00369 } 00370 00371 if (tag.ckID == FOURCC_icon) { 00372 /* 00373 * We've found what we're looking for. Get current position 00374 * in file to be used as the base from which the icon data 00375 * offsets are offset from. 00376 */ 00377 offResBase = (int)(pfi->pFilePtr - pfi->pFileMap); 00378 00379 /* 00380 * Grab the header first, since the following code assumes 00381 * it was read above. 00382 */ 00383 ReadFilePtr(pfi, &pnh, sizeof(NEWHEADER)); 00384 00385 /* 00386 * Break out and let the icon loading/cursor creating code 00387 * take it from here. 00388 */ 00389 break; 00390 } else { 00391 SkipChunk(pfi, &tag); 00392 } 00393 } else { 00394 /* 00395 * Something bad happened in the type read, if it was 00396 * a file error then close and exit, otherwise just 00397 * skip the rest of the chunk 00398 */ 00399 if(!fOK) { 00400 return NULL; 00401 } 00402 /* 00403 * take the type we just read out of the tag size and 00404 * skip the rest 00405 */ 00406 tag.ckSize -= sizeof(DWORD); 00407 SkipChunk(pfi, &tag); 00408 } 00409 } else { 00410 /* 00411 * We're not interested in this chunk, skip it. 00412 */ 00413 SkipChunk(pfi, &tag); 00414 } 00415 } 00416 } else { // not a RIFF file. 00417 if ((pnh->ResType != FT_ICON) && (pnh->ResType != FT_CURSOR)) { 00418 return NULL; 00419 } 00420 } 00421 { 00422 PCURSORRESOURCE pcres; 00423 00424 pcres = ReadIconGuts(pfi, 00425 pnh, 00426 offResBase, 00427 prt, 00428 cxDesired, 00429 cyDesired, 00430 LR_flags); 00431 00432 return ConvertDIBIcon((LPBITMAPINFOHEADER)pcres, 00433 NULL, 00434 pfi->pszName, 00435 *prt == RT_ICON, 00436 cxDesired, 00437 cyDesired, 00438 LR_flags); 00439 } 00440 } 00441 00442 00443 /***********************************************************************\ 00444 * ReadIconGuts 00445 * 00446 * Returns: a pointer to a locally allocated buffer extraced from the 00447 * given file that looks like a icon/acon resource. 00448 * Also returns the type of the icon (RT_ICON or RT_CURSOR) 00449 * 00450 * 00451 * 8/23/1995 SanfordS Documented 00452 * 11/16/1995 SanfordS Added LR_flags support 00453 \***********************************************************************/ 00454 PCURSORRESOURCE ReadIconGuts( 00455 IN PFILEINFO pfi, 00456 IN NEWHEADER *pnhBase, 00457 IN int offResBase, 00458 OUT LPWSTR *prt, 00459 IN int cxDesired, 00460 IN int cyDesired, 00461 IN DWORD LR_flags) 00462 { 00463 NEWHEADER *pnh; 00464 int i, Id; 00465 ICONFILERESDIR UNALIGNED *pird; 00466 PCURSORRESOURCE pcres; 00467 RESDIR UNALIGNED *prd; 00468 DWORD cb; 00469 HOTSPOTREC UNALIGNED *phs; 00470 LPBITMAPINFOHEADER pbih; 00471 00472 /* 00473 * Construct a fake array of RESDIR entries using the info at the head 00474 * of the file. Store the data offset in the idIcon WORD so it can be 00475 * returned by RtlGetIdFromDirectory. 00476 */ 00477 pnh = (NEWHEADER *)UserLocalAlloc(0, sizeof(NEWHEADER) + 00478 (pnhBase->ResCount * (sizeof(RESDIR) + sizeof(HOTSPOTREC)))); 00479 if (pnh == NULL) 00480 return NULL; 00481 00482 *pnh = *pnhBase; 00483 prd = (RESDIR UNALIGNED *)(pnh + 1); 00484 phs = (HOTSPOTREC UNALIGNED *)(prd + pnhBase->ResCount); 00485 00486 for (i = 0; i < (int)pnh->ResCount; i++, prd++) { 00487 /* 00488 * Read the resource directory from the icon file. 00489 */ 00490 ReadFilePtrUnaligned(pfi, &pird, sizeof(ICONFILERESDIR)); 00491 00492 /* 00493 * Convert from the icon editor's resource directory format 00494 * to the post-RC.EXE format LookupIconIdFromDirectory expects. 00495 */ 00496 prd->Icon.Width = pird->bWidth; 00497 prd->Icon.Height = pird->bHeight; 00498 if (pnh->ResType == FT_ICON) { // ICON 00499 prd->Icon.ColorCount = pird->bColorCount; 00500 prd->Icon.reserved = 0; 00501 } 00502 prd->Planes = 0; // Hopefully nobody uses this 00503 prd->BitCount = 0; // " " 00504 prd->BytesInRes = pird->dwDIBSize; 00505 prd->idIcon = (WORD)pird->dwDIBOffset; 00506 00507 phs->xHotspot = pird->xHotspot; 00508 phs->yHotspot = pird->yHotspot; 00509 phs++; 00510 } 00511 00512 *prt = pnhBase->ResType == FT_ICON ? RT_ICON : RT_CURSOR; 00513 Id = RtlGetIdFromDirectory((PBYTE)pnh, 00514 *prt == RT_ICON, 00515 cxDesired, 00516 cyDesired, 00517 LR_flags, 00518 &cb); 00519 00520 /* 00521 * Allocate for worst case (cursor). 00522 */ 00523 pcres = (PCURSORRESOURCE)UserLocalAlloc(0, 00524 cb + FIELD_OFFSET(CURSORRESOURCE, bih)); 00525 if (pcres == NULL) { 00526 goto CleanExit; 00527 } 00528 00529 if (*prt == RT_CURSOR) { 00530 /* 00531 * Fill in hotspot info for cursors. 00532 */ 00533 prd = (RESDIR UNALIGNED *)(pnh + 1); 00534 phs = (HOTSPOTREC UNALIGNED *)(prd + pnh->ResCount); 00535 00536 for( i = 0; i < pnh->ResCount; i++ ) { 00537 if (prd[i].idIcon == (WORD)Id) { 00538 pcres->xHotspot = phs[i].xHotspot; 00539 pcres->yHotspot = phs[i].yHotspot; 00540 break; 00541 } 00542 } 00543 00544 if (i == pnh->ResCount) { 00545 pcres->xHotspot = pird->xHotspot; 00546 pcres->yHotspot = pird->yHotspot; 00547 } 00548 pbih = &pcres->bih; 00549 } else { 00550 pbih = (LPBITMAPINFOHEADER)pcres; 00551 } 00552 00553 /* 00554 * Read in the header information into pcres. 00555 */ 00556 pfi->pFilePtr = pfi->pFileMap + offResBase + Id; 00557 if (!ReadFilePtrCopy(pfi, pbih, cb)) { 00558 UserLocalFree(pnh); 00559 UserLocalFree(pcres); 00560 return NULL; 00561 } 00562 00563 00564 CleanExit: 00565 UserLocalFree(pnh); 00566 return pcres; 00567 } 00568 00569 00570 /***************************************************************************\ 00571 * CreateAniIcon 00572 * 00573 * For now, CreateAniIcon copies the jif rate table and the sequence table 00574 * but not the CURSOR structs. This is ok as long as this routine is 00575 * internal only. 00576 * 00577 * History: 00578 * 10-02-91 DarrinM Created. 00579 \***************************************************************************/ 00580 00581 HCURSOR CreateAniIcon( 00582 LPCWSTR pszName, 00583 LPWSTR rt, 00584 int cicur, 00585 DWORD *aicur, 00586 int cpcur, 00587 HCURSOR *ahcur, 00588 JIF jifRate, 00589 PJIF ajifRate, 00590 BOOL fPublic) 00591 { 00592 HCURSOR hacon; 00593 CURSORDATA acon; 00594 DWORD cbacon; 00595 HCURSOR *ahcurT; // Array of image frame pointers 00596 DWORD *aicurT; // Array of frame indices (sequence table) 00597 PJIF ajifRateT; // Array of time offsets 00598 int i; 00599 00600 /* 00601 * Start by allocating space for the ACON structure and the ahcur and 00602 * ajifRate arrays. 00603 */ 00604 hacon = (HCURSOR)NtUserCallOneParam(fPublic, 00605 SFI__CREATEEMPTYCURSOROBJECT); 00606 if (hacon == NULL) 00607 return NULL; 00608 00609 /* 00610 * Save a couple LocalAlloc calls by allocating the memory needed for 00611 * the CURSOR, JIF, and SEQ arrays at once. 00612 */ 00613 RtlZeroMemory(&acon, sizeof(acon)); 00614 cbacon = (cpcur * sizeof(HCURSOR)) + 00615 (cicur * sizeof(JIF)) + (cicur * sizeof(DWORD)); 00616 ahcurT = (HCURSOR *)UserLocalAlloc(HEAP_ZERO_MEMORY, cbacon); 00617 if (ahcurT == NULL) { 00618 NtUserDestroyCursor((HCURSOR)hacon, CURSOR_ALWAYSDESTROY); 00619 return NULL; 00620 } 00621 acon.aspcur = (PCURSOR *)ahcurT; 00622 00623 /* 00624 * Set up work pointers 00625 */ 00626 ajifRateT = (PJIF)((PBYTE)ahcurT + (cpcur * sizeof(HCURSOR))); 00627 aicurT = (DWORD *)((PBYTE)ajifRateT + (cicur * sizeof(JIF))); 00628 00629 /* 00630 * Save offsets to arrays to make copying them to the server 00631 * easier. 00632 */ 00633 acon.ajifRate = (PJIF)(cpcur * sizeof(HCURSOR)); 00634 acon.aicur = (DWORD *)((PBYTE)acon.ajifRate + (cicur * sizeof(JIF))); 00635 00636 acon.cpcur = cpcur; 00637 acon.cicur = cicur; 00638 00639 acon.CURSORF_flags = CURSORF_ACON; 00640 00641 /* 00642 * Store this information away so we can identify 00643 * repeated calls to LoadCursor/Icon for the same 00644 * resource type/id. 00645 */ 00646 acon.rt = PTR_TO_ID(rt); 00647 acon.lpModName = szUSER32; 00648 acon.lpName = (LPWSTR)pszName; 00649 00650 /* 00651 * Make a private copy of the cursor pointers and the animation rate table. 00652 */ 00653 for (i = 0; i < cpcur; i++) { 00654 ahcurT[i] = ahcur[i]; 00655 // ahcurT[i]->fPointer |= PTRI_ANIMATED; // if GDI needs it 00656 00657 } 00658 00659 for (i = 0; i < cicur; i++) { 00660 00661 /* 00662 * If constant rate, initialize the rate table to a single value. 00663 */ 00664 if (ajifRate == NULL) 00665 ajifRateT[i] = jifRate; 00666 else 00667 ajifRateT[i] = ajifRate[i]; 00668 00669 /* 00670 * If no sequence table then build a unity map to the cursor table. 00671 */ 00672 if (aicur == NULL) 00673 aicurT[i] = i; 00674 else 00675 aicurT[i] = aicur[i]; 00676 } 00677 00678 /* 00679 * Stuff acon data into the cursor 00680 */ 00681 if (!_SetCursorIconData(hacon, &acon)) { 00682 NtUserDestroyCursor(hacon, CURSOR_ALWAYSDESTROY); 00683 hacon = NULL; 00684 } 00685 UserLocalFree(ahcurT); 00686 00687 return hacon; 00688 } 00689 00690 00691 /***************************************************************************\ 00692 * ReadIconFromFileMap 00693 * 00694 * LATER: Error handling. 00695 * 00696 * History: 00697 * 12-21-91 DarrinM Created. 00698 \***************************************************************************/ 00699 00700 HCURSOR ReadIconFromFileMap( 00701 PFILEINFO pfi, 00702 int cbSize, // used to seek past this chunk in case of error 00703 DWORD cxDesired, 00704 DWORD cyDesired, 00705 DWORD LR_flags) 00706 { 00707 PCURSORRESOURCE pcres; 00708 HCURSOR hcur = NULL; 00709 LPNEWHEADER pnh; 00710 int offResBase; 00711 LPWSTR rt; 00712 00713 /* 00714 * Get current position in file to be used as the base from which 00715 * the icon data offsets are offset from. 00716 */ 00717 offResBase = (int)(pfi->pFilePtr - pfi->pFileMap); 00718 00719 /* 00720 * Read the .ICO/.CUR data's header. 00721 */ 00722 ReadFilePtr(pfi, &pnh, sizeof(NEWHEADER)); 00723 00724 pcres = ReadIconGuts(pfi, 00725 pnh, 00726 offResBase, 00727 &rt, 00728 cxDesired, 00729 cyDesired, 00730 LR_flags); 00731 00732 if (pcres != NULL) { 00733 hcur = (HCURSOR)ConvertDIBIcon((LPBITMAPINFOHEADER)pcres, 00734 NULL, 00735 NULL, 00736 (rt == RT_ICON), 00737 cxDesired, 00738 cyDesired, 00739 LR_ACONFRAME | LR_flags); 00740 00741 UserLocalFree(pcres); 00742 } 00743 00744 /* 00745 * Seek to the end of this chunk, regardless of our current position. 00746 */ 00747 pfi->pFilePtr = pfi->pFileMap + ((offResBase + cbSize + 1) & (~1)); 00748 00749 return hcur; 00750 } 00751 00752 00753 /***************************************************************************\ 00754 * LoadAniIcon 00755 * 00756 * Loads an animatied cursor from a RIFF file. The RIFF file format for 00757 * animated cursors looks like this: 00758 * 00759 * RIFF( 'ACON' 00760 * LIST( 'INFO' 00761 * INAM( <name> ) 00762 * IART( <artist> ) 00763 * ) 00764 * anih( <anihdr> ) 00765 * [rate( <rateinfo> ) ] 00766 * ['seq '( <seq_info> )] 00767 * LIST( 'fram' icon( <icon_file> ) ... ) 00768 * ) 00769 * 00770 * 00771 * History: 00772 * 10-02-91 DarrinM Created. 00773 * 03-17-93 JonPa Rewrote to use RIFF format instead of RAD 00774 * 04-22-93 JonPa Finalized RIFF format (changed from ANI to ACON etc) 00775 * 11/16/1995 SanfordS Added LR_flags support. 00776 \***************************************************************************/ 00777 HICON LoadAniIcon( 00778 IN PFILEINFO pfi, 00779 IN LPWSTR rt, 00780 IN DWORD cxDesired, 00781 IN DWORD cyDesired, 00782 IN DWORD LR_flags) 00783 { 00784 int cpcur, ipcur = 0, i, cicur; 00785 ANIHEADER anih; 00786 ANIHEADER *panih = NULL; 00787 HICON hacon = NULL; 00788 HCURSOR *phcur; 00789 JIF jifRate, *pjifRate; 00790 RTAG tag; 00791 DWORD *picur; 00792 00793 /* 00794 * Position to the beginning of the file. 00795 */ 00796 pfi->pFilePtr = pfi->pFileMap + sizeof(tag); 00797 00798 #if DBG 00799 if ((ULONG_PTR)pfi->pFileEnd != ((ULONG_PTR)(pfi->pFileMap + sizeof (RTAG) + ((RTAG *)(pfi->pFileMap))->ckSize + 1) & ~1)) { 00800 RIPMSG2(RIP_WARNING, "LoadAniIcon: First RIFF chunk has invalid ckSize. Actual:%#lx Expected:%#lx", 00801 ((RTAG *)(pfi->pFileMap))->ckSize, (pfi->pFileEnd - pfi->pFileMap - sizeof(RTAG)) & ~1); 00802 } 00803 #endif 00804 00805 /* read the chunk type */ 00806 if(!ReadFilePtrCopy(pfi, 00807 &tag.ckID, 00808 sizeof(tag.ckID))) { 00809 goto laiFileErr; 00810 } 00811 00812 if (tag.ckID != FOURCC_ACON) 00813 goto laiFileErr; 00814 00815 /* look for 'anih', 'rate', 'seq ', and 'icon' chunks */ 00816 while( ReadTag(pfi, &tag)) { 00817 00818 switch( tag.ckID ) { 00819 case FOURCC_anih: 00820 if (!ReadChunk(pfi, &tag, &anih)) 00821 goto laiFileErr; 00822 00823 if (!(anih.fl & AF_ICON) || (anih.cFrames == 0)) 00824 goto laiFileErr; 00825 00826 /* 00827 * Allocate space for the ANIHEADER, HCURSOR array and a 00828 * rate table (in case we run into one later). 00829 */ 00830 cpcur = anih.cFrames; 00831 cicur = anih.cSteps; 00832 panih = (PANIHEADER)UserLocalAlloc(HEAP_ZERO_MEMORY, sizeof(ANIHEADER) + 00833 (cicur * sizeof(JIF)) + (cpcur * sizeof(HCURSOR)) + 00834 (cicur * sizeof(DWORD))); 00835 00836 if (panih == NULL) 00837 goto laiFileErr; 00838 00839 00840 phcur = (HCURSOR *)((PBYTE)panih + sizeof(ANIHEADER)); 00841 pjifRate = NULL; 00842 picur = NULL; 00843 00844 *panih = anih; 00845 jifRate = panih->jifRate; 00846 break; 00847 00848 00849 case FOURCC_rate: 00850 /* 00851 * If we find a rate chunk, read it into its preallocated 00852 * space. 00853 */ 00854 pjifRate = (PJIF)((PBYTE)phcur + cpcur * sizeof(HCURSOR)); 00855 if(!ReadChunk(pfi, &tag, (PBYTE)pjifRate)) 00856 goto laiFileErr; 00857 break; 00858 00859 00860 case FOURCC_seq: 00861 /* 00862 * If we find a seq chunk, read it into its preallocated 00863 * space. 00864 */ 00865 picur = (DWORD *)((PBYTE)phcur + cpcur * sizeof(HCURSOR) + 00866 cicur * sizeof(JIF)); 00867 if(!ReadChunk(pfi, &tag, (PBYTE)picur)) 00868 goto laiFileErr; 00869 break; 00870 00871 00872 case FOURCC_LIST: 00873 { 00874 DWORD cbChunk = (tag.ckSize + 1) & ~1; 00875 00876 /* 00877 * See if this list is the 'fram' list of icon chunks 00878 */ 00879 if(!ReadFilePtrCopy(pfi, &tag.ckID, sizeof(tag.ckID))) { 00880 goto laiFileErr; 00881 } 00882 00883 cbChunk -= sizeof(tag.ckID); 00884 00885 if (tag.ckID != FOURCC_fram) { 00886 /* 00887 * Not the fram list (probably the INFO list). Skip 00888 * the rest of this chunk. (Don't forget that we have 00889 * already skipped one dword!) 00890 */ 00891 tag.ckSize = cbChunk; 00892 SkipChunk(pfi, &tag); 00893 break; 00894 } 00895 00896 while(cbChunk >= sizeof(tag)) { 00897 if (!ReadTag(pfi, &tag)) 00898 goto laiFileErr; 00899 00900 cbChunk -= sizeof(tag); 00901 00902 if(tag.ckID == FOURCC_icon) { 00903 00904 /* 00905 * Ok, load the icon/cursor bits, create a cursor from 00906 * them, and save a pointer to it away in the ACON 00907 * cursor pointer array. 00908 */ 00909 phcur[ipcur] = ReadIconFromFileMap(pfi, 00910 tag.ckSize, 00911 cxDesired, 00912 cyDesired, 00913 LR_flags); 00914 00915 if (phcur[ipcur] == NULL) { 00916 for (i = 0; i < ipcur; i++) 00917 NtUserDestroyCursor(phcur[i], 0); 00918 goto laiFileErr; 00919 } 00920 00921 ipcur++; 00922 } else { 00923 /* 00924 * Unknown chunk in fram list, just ignore it 00925 */ 00926 SkipChunk(pfi, &tag); 00927 } 00928 00929 cbChunk -= (tag.ckSize + 1) & ~1; 00930 } 00931 } 00932 break; 00933 00934 default: 00935 /* 00936 * We're not interested in this chunk, skip it. 00937 */ 00938 if(!SkipChunk(pfi, &tag)) 00939 goto laiFileErr; 00940 break; 00941 00942 } 00943 00944 } 00945 00946 /* 00947 * Sanity check the count of frames so we won't fault trying 00948 * to select a nonexistant cursor 00949 */ 00950 if (cpcur != ipcur) { 00951 RIPMSG2(RIP_WARNING, "LoadAniIcon: Invalid number of frames; Actual:%#lx Expected:%#lx", 00952 ipcur, cpcur); 00953 for (i = 0; i < ipcur; i++) 00954 NtUserDestroyCursor(phcur[i], CURSOR_ALWAYSDESTROY); 00955 goto laiFileErr; 00956 } 00957 00958 00959 00960 if (cpcur != 0) 00961 hacon = CreateAniIcon(pfi->pszName, 00962 rt, 00963 cicur, 00964 picur, 00965 cpcur, 00966 phcur, 00967 jifRate, 00968 pjifRate, 00969 LR_flags & LR_GLOBAL); 00970 00971 laiFileErr: 00972 00973 #if DBG 00974 if (hacon == NULL) { 00975 RIPMSG0(RIP_WARNING, "LoadAniIcon: Invalid icon data format"); 00976 } 00977 #endif 00978 00979 if (panih != NULL) 00980 UserLocalFree(panih); 00981 00982 return hacon; 00983 }

Generated on Sat May 15 19:39:13 2004 for test by doxygen 1.3.7