Annotation of mstools/samples/sdktools/imagedit/rwicocur.c, revision 1.1.1.1

1.1       root        1: /****************************************************************************/
                      2: /*                                                                          */
                      3: /*                         Microsoft Confidential                           */
                      4: /*                                                                          */
                      5: /*                 Copyright (c) Microsoft Corp.  1987, 1991                */
                      6: /*                           All Rights Reserved                            */
                      7: /*                                                                          */
                      8: /****************************************************************************/
                      9: /****************************** Module Header *******************************
                     10: * Module Name: rwicocur.c
                     11: *
                     12: * Routines to read and write icon and cursor files.
                     13: *
                     14: * History:
                     15: *
                     16: ****************************************************************************/
                     17: 
                     18: #include "imagedit.h"
                     19: 
                     20: #include <io.h>
                     21: #include <fcntl.h>                          // For NT fstat().
                     22: #include <sys\types.h>                      // For fstat() types.
                     23: #include <sys\stat.h>                       // For fstat() function.
                     24: 
                     25: 
                     26: 
                     27: /************************************************************************
                     28: * LoadIconCursorFile
                     29: *
                     30: * Loads the specified icon or cursor file.  It reads the images into
                     31: * a list, then prompts for which one to open initially.
                     32: *
                     33: * Arguments:
                     34: *
                     35: * History:
                     36: *
                     37: ************************************************************************/
                     38: 
                     39: BOOL LoadIconCursorFile(
                     40:     PSTR pszFullFileName,
                     41:     BOOL fIcon)
                     42: {
                     43:     HFILE hf;
                     44:     INT i;
                     45:     PIMAGEINFO pImage;
                     46:     LPBITMAPINFO lpBitmapInfo;
                     47:     HANDLE hDIB;                    // Handle to DIB bits.
                     48:     OFSTRUCT OfStruct;
                     49:     struct stat FileStatus;
                     50:     ICOCURSORHDR hdr;               // Header structure of icon/cursor file.
                     51:     INT nImages;
                     52:     PICOCURSORDESC aIcoCurDesc;     // Array of ico/cur descriptors.
                     53:     DWORD dwFilePos;
                     54:     DWORD dwFileSize;
                     55:     INT iType;
                     56: 
                     57:     if ((hf = (HFILE)OpenFile(pszFullFileName, (LPOFSTRUCT)&OfStruct, OF_READ))
                     58:             == (HFILE)-1) {
                     59:         Message(MSG_CANTOPEN, pszFullFileName);
                     60:         return FALSE;
                     61:     }
                     62: 
                     63:     fstat((INT)_open_osfhandle((long)(hf), (int)(O_RDONLY)), &FileStatus);
                     64:     dwFileSize = (DWORD)FileStatus.st_size;
                     65: 
                     66:     ImageLinkFreeList();
                     67: 
                     68:     if (fIcon)
                     69:         iType = FT_ICON;
                     70:     else
                     71:         iType = FT_CURSOR;
                     72: 
                     73:     /*
                     74:      * Read the Icon/Cursor File header.
                     75:      */
                     76:     if (!MyFileRead(hf, (LPSTR)&hdr, sizeof(ICOCURSORHDR),
                     77:             pszFullFileName, iType))
                     78:         goto Error1;
                     79: 
                     80:     if (hdr.iReserved != 0) {
                     81:         Message(MSG_BADICOCURFILE, pszFullFileName);
                     82:         goto Error1;
                     83:     }
                     84: 
                     85:     /*
                     86:      * Get number of images in the file.
                     87:      */
                     88:     nImages = hdr.iResourceCount;
                     89: 
                     90:     if (!nImages || nImages > MAXIMAGES) {
                     91:         Message(MSG_BADICOCURFILE, pszFullFileName);
                     92:         goto Error1;
                     93:     }
                     94: 
                     95:     if (hdr.iResourceType != 1 && hdr.iResourceType != 2) {
                     96:         Message(MSG_BADICOCURFILE, pszFullFileName);
                     97:         goto Error1;
                     98:     }
                     99: 
                    100:     /*
                    101:      * Allocate room for the descriptor records.
                    102:      */
                    103:     if (!(aIcoCurDesc = (PICOCURSORDESC)MyAlloc(
                    104:             sizeof(ICOCURSORDESC) * nImages)))
                    105:         goto Error1;
                    106: 
                    107:     /*
                    108:      * Read in the descriptor records.
                    109:      */
                    110:     if (!MyFileRead(hf, (LPSTR)aIcoCurDesc, sizeof(ICOCURSORDESC) * nImages,
                    111:             pszFullFileName, iType))
                    112:         goto Error2;
                    113: 
                    114:     /*
                    115:      * Get the current file position (after the descriptors).  This
                    116:      * should be the start of the DIB's.
                    117:      */
                    118:     dwFilePos = (DWORD)SetFilePointer((HANDLE)hf, 0, NULL, (DWORD)1);
                    119: 
                    120:     /*
                    121:      * Validate the descriptor records.
                    122:      */
                    123:     for (i = 0; i < nImages; i++) {
                    124:         /*
                    125:          * Make sure the DIB's are sequential (not overlapping)
                    126:          * and they all fit within the file.
                    127:          */
                    128:         if (aIcoCurDesc[i].DIBOffset != dwFilePos ||
                    129:                 dwFilePos + aIcoCurDesc[i].DIBSize > dwFileSize) {
                    130:             Message(MSG_BADICOCURFILE, pszFullFileName);
                    131:             goto Error2;
                    132:         }
                    133: 
                    134:         /*
                    135:          * Jump to the next DIB.
                    136:          */
                    137:         dwFilePos += aIcoCurDesc[i].DIBSize;
                    138:     }
                    139: 
                    140:     for (i = 0; i < nImages; i++) {
                    141:         pImage = ImageLinkAlloc(NULL, 0, 0,
                    142:                 aIcoCurDesc[i].iHotspotX, aIcoCurDesc[i].iHotspotY,
                    143:                 (aIcoCurDesc[i].iColorCount == (BYTE)8) ?
                    144:                 aIcoCurDesc[i].iColorCount : 0);
                    145: 
                    146:         if (!pImage)
                    147:             goto Error3;
                    148: 
                    149:         /*
                    150:          * Allocate space for the DIB for this image.
                    151:          */
                    152:         if (!(hDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
                    153:                 (DWORD)aIcoCurDesc[i].DIBSize))) {
                    154:             Message(MSG_OUTOFMEMORY);
                    155:             goto Error3;
                    156:         }
                    157: 
                    158:         pImage->DIBSize = aIcoCurDesc[i].DIBSize;
                    159:         pImage->DIBhandle = hDIB;
                    160:         pImage->DIBPtr = (LPSTR)GlobalLock(hDIB);
                    161:     }
                    162: 
                    163:     for (pImage = gpImageHead; pImage != NULL; pImage = pImage->pImageNext) {
                    164:         if (!MyFileRead(hf, pImage->DIBPtr, (DWORD)pImage->DIBSize,
                    165:                 pszFullFileName, iType))
                    166:             goto Error3;
                    167: 
                    168:         lpBitmapInfo = (LPBITMAPINFO)pImage->DIBPtr;
                    169: 
                    170:         if (!IsValidDIB(lpBitmapInfo, pImage->DIBSize, TRUE)) {
                    171:             Message(MSG_BADICOCURFILE, pszFullFileName);
                    172:             goto Error3;
                    173:         }
                    174: 
                    175:         /*
                    176:          * Fill the x and y size fields in image node from
                    177:          * information in the DIB header.
                    178:          */
                    179:         pImage->cx = (INT)lpBitmapInfo->bmiHeader.biWidth;
                    180:         pImage->cy = (INT)lpBitmapInfo->bmiHeader.biHeight / 2;
                    181:         if (pImage->nColors == 0)
                    182:             pImage->nColors = (1 << lpBitmapInfo->bmiHeader.biBitCount);
                    183: 
                    184:         pImage->pDevice = DeviceLinkFind(
                    185:                 fIcon ? gpIconDeviceHead : gpCursorDeviceHead,
                    186:                 pImage->nColors, pImage->cx, pImage->cy);
                    187:     }
                    188: 
                    189:     _lclose((HFILE)hf);
                    190: 
                    191:     fFileDirty = FALSE;
                    192:     SetFileName(pszFullFileName);
                    193:     giType = iType;
                    194: 
                    195:     gnImages = nImages;
                    196: 
                    197:     /*
                    198:      * Update the PropBar and the Toolbox so that they show
                    199:      * information about the opened file.  We do this now just
                    200:      * in case the user cancels out of the Image Select Dialog.
                    201:      */
                    202:     PropBarUpdate();
                    203:     ToolboxUpdate();
                    204: 
                    205:     /*
                    206:      * Open up an image.  If there are multiple images in the file,
                    207:      * show the Image Select dialog.  We also show the Image Select
                    208:      * dialog if the file only has one image but it is not for a known
                    209:      * device.
                    210:      */
                    211:     if (gnImages > 1 || !gpImageHead->pDevice)
                    212:         ImageSelectDialog();
                    213:     else
                    214:         ImageOpen2(gpImageHead);
                    215: 
                    216:     return TRUE;
                    217: 
                    218: Error3:
                    219:     ImageLinkFreeList();
                    220: 
                    221: Error2:
                    222:     MyFree(aIcoCurDesc);
                    223: 
                    224: Error1:
                    225:     _lclose((HFILE)hf);
                    226: 
                    227:     return FALSE;
                    228: }
                    229: 
                    230: 
                    231: 
                    232: /************************************************************************
                    233: * IsValidDIB
                    234: *
                    235: * This function determines if the given DIB is valid or not.  It does
                    236: * this without touching memory outside the bounds of the cbDIBSize
                    237: * passed in or the size of a BITMAPINFOHEADER, whichever is smaller.
                    238: * Note that even if the DIB is valid, however, the current image
                    239: * editor might not be able to edit it (the size might be too big, for
                    240: * instance).
                    241: *
                    242: * Arguments:
                    243: *   LPBITMAPINFO pDIB - Points to the DIB.
                    244: *   DWORD cbDIBSize   - The size of the DIB.
                    245: *   BOOL fIcoCur      - TRUE if this is an icon or cursor.  This effects
                    246: *                       whether an AND mask is expected to be in the DIB.
                    247: *
                    248: * History:
                    249: *
                    250: ************************************************************************/
                    251: 
                    252: BOOL IsValidDIB(
                    253:     LPBITMAPINFO pDIB,
                    254:     DWORD cbDIBSize,
                    255:     BOOL fIcoCur)
                    256: {
                    257:     DWORD cbANDMask;
                    258:     DWORD cbXORMask;
                    259:     DWORD cbColorTable;
                    260:     DWORD nHeight;
                    261: 
                    262:     if (cbDIBSize < sizeof(BITMAPINFOHEADER))
                    263:         return FALSE;
                    264: 
                    265:     if (pDIB->bmiHeader.biSize != sizeof(BITMAPINFOHEADER))
                    266:         return FALSE;
                    267: 
                    268:     if (pDIB->bmiHeader.biPlanes != 1)
                    269:         return FALSE;
                    270: 
                    271:     if (pDIB->bmiHeader.biBitCount != 1 &&
                    272:             pDIB->bmiHeader.biBitCount != 4 &&
                    273:             pDIB->bmiHeader.biBitCount != 8 &&
                    274:             pDIB->bmiHeader.biBitCount != 24)
                    275:         return FALSE;
                    276: 
                    277:     if (fIcoCur) {
                    278:         nHeight = pDIB->bmiHeader.biHeight / 2;
                    279:         cbANDMask = (((pDIB->bmiHeader.biWidth + 31) & 0xffffffe0) >> 3) *
                    280:                 nHeight;
                    281:     }
                    282:     else {
                    283:         nHeight = pDIB->bmiHeader.biHeight;
                    284:         cbANDMask = 0;
                    285:     }
                    286: 
                    287:     cbColorTable = (1 << pDIB->bmiHeader.biBitCount) * sizeof(RGBQUAD);
                    288:     cbXORMask = ((((pDIB->bmiHeader.biWidth * pDIB->bmiHeader.biBitCount) +
                    289:             31) & 0xffffffe0) >> 3) * nHeight;
                    290: 
                    291:     /*
                    292:      * Check the size field in the header.  This must be either zero
                    293:      * or a valid size.
                    294:      */
                    295:     if (pDIB->bmiHeader.biSizeImage &&
                    296:             pDIB->bmiHeader.biSizeImage != cbXORMask + cbANDMask)
                    297:         return FALSE;
                    298: 
                    299:     if (cbDIBSize != sizeof(BITMAPINFOHEADER) + cbColorTable +
                    300:             cbXORMask + cbANDMask)
                    301:         return FALSE;
                    302: 
                    303:     return TRUE;
                    304: }
                    305: 
                    306: 
                    307: 
                    308: /************************************************************************
                    309: * SaveIconCursorFile
                    310: *
                    311: *
                    312: *
                    313: * Arguments:
                    314: *
                    315: * Returns:
                    316: *   TRUE if successful, FALSE otherwise.
                    317: *
                    318: * History:
                    319: *
                    320: ************************************************************************/
                    321: 
                    322: BOOL SaveIconCursorFile(
                    323:     PSTR pszFullFileName,
                    324:     INT iType)
                    325: {
                    326:     ICOCURSORHDR IcoCurHdr;     // Header structure of icon/cursor file.
                    327:     ICOCURSORDESC IcoCurDesc;   // Icon/cursor descriptor struct.
                    328:     HCURSOR hcurOld;            // Handle to old cursor.
                    329:     PIMAGEINFO pImage;          // Pointer to node in image list.
                    330:     DWORD iBitsOffset;          // Offset of the actual DIB bits for image.
                    331:     HFILE hf;
                    332:     OFSTRUCT OfStruct;
                    333: 
                    334:     hcurOld = SetCursor(hcurWait);
                    335: 
                    336:     /*
                    337:      * Save the bits of the current image.
                    338:      */
                    339:     ImageSave();
                    340: 
                    341:     /*
                    342:      * Open the file for writing.
                    343:      */
                    344:     if ((hf = (HFILE)OpenFile(pszFullFileName, &OfStruct, OF_CREATE | OF_READWRITE))
                    345:             == (HFILE)-1) {
                    346:         Message(MSG_CANTCREATE, pszFullFileName);
                    347:         goto Error1;
                    348:     }
                    349: 
                    350:     /*
                    351:      * This is crucial since this helps distinguish a 3.0 icon/cursor
                    352:      * from an old, old (2.1 format) icon/cursor, which has meaningful
                    353:      * information in this WORD.
                    354:      */
                    355:     IcoCurHdr.iReserved = (WORD)0;
                    356: 
                    357:     if (iType == FT_ICON)
                    358:         IcoCurHdr.iResourceType = 1;        // Icon type.
                    359:     else
                    360:         IcoCurHdr.iResourceType = 2;        // Cursor type.
                    361: 
                    362:     IcoCurHdr.iResourceCount = (WORD)gnImages;
                    363: 
                    364:     /*
                    365:      * Write the header to disk.
                    366:      */
                    367:     if (!MyFileWrite(hf, (LPSTR)&IcoCurHdr, sizeof(ICOCURSORHDR),
                    368:             pszFullFileName))
                    369:         goto Error2;
                    370: 
                    371:     /*
                    372:      * Write all the descriptors.
                    373:      */
                    374:     iBitsOffset = sizeof(ICOCURSORHDR) + (gnImages * sizeof(ICOCURSORDESC));
                    375:     for (pImage = gpImageHead; pImage; pImage = pImage->pImageNext) {
                    376:         IcoCurDesc.iWidth = (BYTE)pImage->cx;
                    377:         IcoCurDesc.iHeight = (BYTE)pImage->cy;
                    378:         IcoCurDesc.iColorCount = (giType == FT_ICON) ?
                    379:                 (BYTE)pImage->nColors : (BYTE)0;
                    380:         IcoCurDesc.iUnused = 0;
                    381:         IcoCurDesc.iHotspotX = (WORD)pImage->iHotspotX;
                    382:         IcoCurDesc.iHotspotY = (WORD)pImage->iHotspotY;
                    383:         IcoCurDesc.DIBSize = pImage->DIBSize;
                    384:         IcoCurDesc.DIBOffset = iBitsOffset;
                    385: 
                    386:         if (!MyFileWrite(hf, (LPSTR)&IcoCurDesc, sizeof(ICOCURSORDESC),
                    387:                 pszFullFileName))
                    388:             goto Error2;
                    389: 
                    390:         iBitsOffset += IcoCurDesc.DIBSize;
                    391:     }
                    392: 
                    393:     /*
                    394:      * Now write the DIB's.
                    395:      */
                    396:     for (pImage = gpImageHead; pImage; pImage = pImage->pImageNext) {
                    397:         if (!MyFileWrite(hf, (LPSTR)pImage->DIBPtr,
                    398:                 (DWORD)pImage->DIBSize, pszFullFileName))
                    399:             goto Error2;
                    400:     }
                    401: 
                    402:     _lclose((HFILE)hf);
                    403: 
                    404:     fFileDirty = FALSE;
                    405:     SetFileName(pszFullFileName);
                    406: 
                    407:     SetCursor(hcurOld);
                    408: 
                    409:     return TRUE;
                    410: 
                    411: Error2:
                    412:     _lclose((HFILE)hf);
                    413: 
                    414: Error1:
                    415:     SetCursor(hcurOld);
                    416: 
                    417:     return FALSE;
                    418: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.