|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.