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

clres.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: clres.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * Resource Loading/Creation Routines 00007 * 00008 * History: 00009 * 24-Sep-1990 MikeKe From win30 00010 * 19-Sep-1995 ChrisWil Win95/NT merge. 00011 \***************************************************************************/ 00012 00013 #include "precomp.h" 00014 #pragma hdrstop 00015 00016 /* 00017 * Constants. 00018 */ 00019 #define BPP01_MAXCOLORS 2 00020 #define BPP04_MAXCOLORS 16 00021 #define BPP08_MAXCOLORS 256 00022 00023 #define RESCLR_BLACK 0x00000000 00024 #define RESCLR_WHITE 0x00FFFFFF 00025 00026 typedef struct { 00027 ACCEL accel; 00028 WORD padding; 00029 } RESOURCE_ACCEL, *PRESOURCE_ACCEL; 00030 00031 /* 00032 * Bitmap resource IDs 00033 */ 00034 #define BMR_ICON 1 00035 #define BMR_BITMAP 2 00036 #define BMR_CURSOR 3 00037 00038 typedef struct _OLDCURSOR { 00039 BYTE bType; 00040 BYTE bFormat; 00041 WORD xHotSpot; // 0 for icons 00042 WORD yHotSpot; // 0 for icons 00043 WORD cx; 00044 WORD cy; 00045 WORD cxBytes; 00046 WORD wReserved2; 00047 BYTE abBitmap[1]; 00048 } OLDCURSOR, *POLDCURSOR; 00049 typedef OLDCURSOR UNALIGNED *UPOLDCURSOR; 00050 00051 /* 00052 * Local Macros. 00053 */ 00054 #define GETINITDC() \ 00055 (gfSystemInitialized ? NtUserGetDC(NULL) : CreateDCW(L"DISPLAY", L"", NULL, NULL)) 00056 00057 #define RELEASEINITDC(hdc) \ 00058 (gfSystemInitialized ? ReleaseDC(NULL, hdc) : DeleteDC(hdc)) 00059 00060 #define ISRIFFFORMAT(p) \ 00061 (((UNALIGNED RTAG *)(p))->ckID == FOURCC_RIFF) 00062 00063 #define MR_FAILFOR40 0x01 00064 #define MR_MONOCHROME 0x02 00065 00066 00067 typedef struct tagMAPRES { 00068 WORD idDisp; // display driver ID 00069 WORD idUser; // USER ID 00070 BYTE bFlags; // Flags 00071 BYTE bReserved; // unused 00072 } MAPRES, *LPMAPRES, *PMAPRES; 00073 00074 00075 HBITMAP CopyBmp(HBITMAP hbmpOrg, int cxNew, int cyNew, UINT LR_flags); 00076 00077 /***************************************************************************\ 00078 * SplFindResource 00079 * 00080 * Check whether the hInstance passed is that of the present display driver; 00081 * if so, it will call the GetDriverResourceId() in the display to allow 00082 * it to map the given id/name to a new id/name. Then it will call 00083 * FindResource9) in KERNEL. 00084 * 00085 * 13-Nov-1995 SanfordS Added mapping for DEFAULT constants. 00086 \***************************************************************************/ 00087 00088 HANDLE SplFindResource( 00089 HINSTANCE hmod, 00090 LPCWSTR lpName, 00091 LPCWSTR lpType) 00092 { 00093 return FINDRESOURCEW(hmod, lpName, lpType); 00094 } 00095 00096 /***************************************************************************\ 00097 * SplFreeResource 00098 * 00099 * Really frees a resource that is shared (won't be touched again unless 00100 * LR_COPYFROMRESOURCE is used) or system. 00101 * 00102 * 13-Nov-1995 SanfordS Added mapping for DEFAULT constants. 00103 \***************************************************************************/ 00104 00105 VOID SplFreeResource( 00106 HANDLE hRes, 00107 HINSTANCE hmod, 00108 UINT lrFlags) 00109 { 00110 if (!FREERESOURCE(hRes, hmod) && 00111 ((hmod == hmodUser) || (lrFlags & LR_SHARED))) { 00112 00113 FREERESOURCE(hRes, hmod); 00114 } 00115 } 00116 00117 /***********************************************************************\ 00118 * WowGetModuleFileName 00119 * 00120 * This converts a WOW or non-WOW module handle to a string form that 00121 * can be restored even for WOW handles. 00122 * 00123 * Returns: fSuccess 00124 * 00125 * 29-Nov-1995 SanfordS Created. 00126 \***********************************************************************/ 00127 00128 BOOL WowGetModuleFileName( 00129 HMODULE hModule, 00130 LPWSTR pwsz, 00131 DWORD cchMax) 00132 { 00133 if (!GetModuleFileName(hModule, pwsz, cchMax)) { 00134 00135 if (cchMax < 10) { 00136 RIPMSG0(RIP_WARNING, "WowGetModuleFileName: exceeded Char-Max"); 00137 return FALSE; 00138 } 00139 00140 wsprintf(pwsz, TEXT("\001%08lx"), hModule); 00141 } 00142 00143 return TRUE; 00144 } 00145 00146 /***********************************************************************\ 00147 * WowGetModuleHandle 00148 * 00149 * This restores the string form of a module handle created by 00150 * WowGetModuleFileName to the original handle. 00151 * 00152 * Returns: fSuccess 00153 * 00154 * 29-Nov-1995 Created SanfordS 00155 \***********************************************************************/ 00156 00157 HMODULE WowGetModuleHandle( 00158 LPCWSTR pwsz) 00159 { 00160 HMODULE hMod = NULL; 00161 DWORD digit; 00162 00163 if (pwsz[0] == TEXT('\001')) { 00164 00165 /* 00166 * Cant seem to link to swscanf without CRT0 problems so just 00167 * do it by hand. 00168 */ 00169 while (*(++pwsz)) { 00170 00171 if (*pwsz == TEXT(' ')) 00172 continue; 00173 00174 digit = *pwsz - TEXT('0'); 00175 00176 if (digit > 9) 00177 digit += (DWORD)(TEXT('0') - TEXT('a') + 10); 00178 00179 (ULONG_PTR)hMod <<= 4; 00180 (ULONG_PTR)hMod += digit; 00181 } 00182 00183 } else { 00184 00185 hMod = GetModuleHandle(pwsz); 00186 } 00187 00188 return hMod; 00189 } 00190 00191 /***************************************************************************\ 00192 * CreateAcceleratorTableA (API) 00193 * 00194 * Creates an accel table, returns handle to accel table. 00195 * 00196 * 02-May-1991 ScottLu Created. 00197 \***************************************************************************/ 00198 00199 HACCEL WINAPI CreateAcceleratorTableA( 00200 LPACCEL paccel, 00201 int cAccel) 00202 { 00203 int nAccel = cAccel; 00204 LPACCEL pAccelT = paccel; 00205 00206 /* 00207 * Convert any character keys from ANSI to Unicode. 00208 */ 00209 while (nAccel--) { 00210 00211 if ((pAccelT->fVirt & FVIRTKEY) == 0) { 00212 00213 if (!NT_SUCCESS(RtlMultiByteToUnicodeN((LPWSTR)&(pAccelT->key), 00214 sizeof(WCHAR), 00215 NULL, 00216 (LPSTR)&(pAccelT->key), 00217 sizeof(CHAR)))) { 00218 pAccelT->key = 0xFFFF; 00219 } 00220 } 00221 00222 pAccelT++; 00223 } 00224 00225 return NtUserCreateAcceleratorTable(paccel, cAccel); 00226 } 00227 00228 /***************************************************************************\ 00229 * CopyAcceleratorTableA (API) 00230 * 00231 * Copies an accel table 00232 * 00233 * 02-May-1991 ScottLu Created. 00234 \***************************************************************************/ 00235 00236 int CopyAcceleratorTableA( 00237 HACCEL hacc, 00238 LPACCEL paccel, 00239 int length) 00240 { 00241 int retval; 00242 00243 retval = NtUserCopyAcceleratorTable(hacc, paccel, length); 00244 00245 /* 00246 * If we are doing a copy and we succeeded then convert the accelerator 00247 */ 00248 if ((paccel != NULL) && (retval > 0)) { 00249 00250 /* 00251 * Translate UNICODE character keys to ANSI 00252 */ 00253 int nAccel = retval; 00254 LPACCEL pAccelT = paccel; 00255 00256 while (nAccel--) { 00257 if ((pAccelT->fVirt & FVIRTKEY) == 0) { 00258 if (!NT_SUCCESS(RtlUnicodeToMultiByteN((PCHAR)&(pAccelT->key), 00259 sizeof(WCHAR), 00260 NULL, 00261 (PWSTR)&(pAccelT->key), 00262 sizeof(pAccelT->key)))) { 00263 pAccelT->key = 0; 00264 } 00265 } 00266 pAccelT++; 00267 } 00268 } 00269 00270 return retval; 00271 } 00272 00273 /***************************************************************************\ 00274 * FindAccResource 00275 * 00276 * Resource accelerator tables are to be loaded only once to be compatible 00277 * with Win95. So we keep track of the addresses we've loaded tables from 00278 * and the corresponding handle. 00279 * 00280 * This function finds an entry in the table. It returns the address 00281 * of the pacNext pointer that contains the requested entry. 00282 * 00283 * 01/31/97 GerardoB Created. 00284 \***************************************************************************/ 00285 PACCELCACHE * FindAccResource (HACCEL hAccel, PVOID pRes) 00286 { 00287 /************************************ 00288 * The caller must own gcsAccelCache * 00289 *************************************/ 00290 00291 PACCELCACHE * ppacNext = &gpac; 00292 PACCELCACHE pac; 00293 00294 /* 00295 * This is meant to search by handle or by pointer, not both 00296 * So at least one of the parameters must be NULL. 00297 */ 00298 UserAssert(!(hAccel && pRes)); 00299 /* 00300 * Walk the table 00301 */ 00302 while (*ppacNext != NULL) { 00303 pac = *ppacNext; 00304 if ((pac->pRes == pRes) || (pac->hAccel == hAccel)) { 00305 /* 00306 * Found it. Validate this entry before returning. 00307 */ 00308 UserAssert(pac->dwLockCount != 0); 00309 UserAssert(HMValidateHandleNoDesktop(pac->hAccel, TYPE_ACCELTABLE)); 00310 break; 00311 } 00312 00313 ppacNext = &(pac->pacNext); 00314 } 00315 00316 return ppacNext; 00317 } 00318 /***************************************************************************\ 00319 * AddAccResource 00320 * 00321 * This is called everytime LoadAcc loads a new table. It adds an 00322 * entry (handle and resource address) to the global list and 00323 * sets the lock count to 1 00324 * 00325 * 01/31/97 GerardoB Created. 00326 \***************************************************************************/ 00327 void AddAccResource (HACCEL hAccel, PVOID pRes) 00328 { 00329 PACCELCACHE pac; 00330 00331 UserAssert(HMValidateHandleNoDesktop(hAccel, TYPE_ACCELTABLE)); 00332 UserAssert(pRes != NULL); 00333 00334 /* 00335 * Allocate and initialize a new entry. 00336 */ 00337 pac = (PACCELCACHE)LocalAlloc(LPTR, sizeof(ACCELCACHE)); 00338 if (pac != NULL) { 00339 pac->dwLockCount = 1; 00340 pac->hAccel = hAccel; 00341 pac->pRes = pRes; 00342 00343 /* 00344 * Make it the new head of the list 00345 */ 00346 RtlEnterCriticalSection(&gcsAccelCache); 00347 pac->pacNext = gpac; 00348 gpac = pac; 00349 RtlLeaveCriticalSection(&gcsAccelCache); 00350 00351 } 00352 } 00353 /***************************************************************************\ 00354 * DestroyAcceleratorTable 00355 * 00356 * 01/31/97 GerardoB Created. 00357 \***************************************************************************/ 00358 BOOL DestroyAcceleratorTable (HACCEL hAccel) 00359 { 00360 BOOL fUnlocked = TRUE; 00361 PACCELCACHE *ppacNext, pac; 00362 00363 /* 00364 * If we added this table to our list, decrement the lock count 00365 */ 00366 RtlEnterCriticalSection(&gcsAccelCache); 00367 ppacNext = FindAccResource(hAccel, NULL); 00368 if (*ppacNext != NULL) { 00369 pac = *ppacNext; 00370 /* 00371 * Found it. Decrement lock count. 00372 */ 00373 UserAssert(pac->dwLockCount != 0); 00374 fUnlocked = (--pac->dwLockCount == 0); 00375 /* 00376 * If noboby else wants this around, unlink it and nuke it. 00377 */ 00378 if (fUnlocked) { 00379 *ppacNext = pac->pacNext; 00380 LocalFree(pac); 00381 } 00382 } 00383 RtlLeaveCriticalSection(&gcsAccelCache); 00384 00385 /* 00386 * If not totally deref'ed, return FALSE (win95 compat). 00387 */ 00388 if (fUnlocked) { 00389 return NtUserDestroyAcceleratorTable(hAccel); 00390 } else { 00391 return FALSE; 00392 } 00393 } 00394 /***************************************************************************\ 00395 * LoadAcc (Worker) 00396 * 00397 * This is the worker-routine for loading accelerator tables. 00398 * 00399 \***************************************************************************/ 00400 00401 #define FACCEL_VALID (FALT | FCONTROL | FNOINVERT | FSHIFT | FVIRTKEY | FLASTKEY) 00402 00403 HANDLE LoadAcc( 00404 HINSTANCE hmod, 00405 HANDLE hrl) 00406 { 00407 PACCELCACHE * ppacNext; 00408 HANDLE handle = NULL; 00409 00410 if (hrl != NULL) { 00411 00412 if (hrl = LOADRESOURCE(hmod, hrl)) { 00413 00414 PRESOURCE_ACCEL paccel; 00415 00416 if ((paccel = (PRESOURCE_ACCEL)LOCKRESOURCE(hrl, hmod)) != NULL) { 00417 00418 int nAccel = 0; 00419 int i; 00420 LPACCEL paccelT; 00421 00422 /* 00423 * Check if we've already loaded accelerators from this 00424 * same address 00425 */ 00426 RtlEnterCriticalSection(&gcsAccelCache); 00427 ppacNext = FindAccResource(NULL, paccel); 00428 if (*ppacNext != NULL) { 00429 (*ppacNext)->dwLockCount++; 00430 handle = (*ppacNext)->hAccel; 00431 } 00432 RtlLeaveCriticalSection(&gcsAccelCache); 00433 /* 00434 * If we found this table on the global list, 00435 * return the same handle (Win95 compat) 00436 */ 00437 if (handle != NULL) { 00438 goto UnlockAndFree; 00439 } 00440 00441 while (!((paccel[nAccel].accel.fVirt) & FLASTKEY)) { 00442 00443 if (paccel[nAccel].accel.fVirt & ~FACCEL_VALID) { 00444 RIPMSG0(RIP_WARNING, "LoadAcc: Invalid Parameter"); 00445 goto UnlockAndFree; 00446 } 00447 00448 nAccel++; 00449 } 00450 00451 if (paccel[nAccel].accel.fVirt & ~FACCEL_VALID) { 00452 RIPMSG0(RIP_WARNING, "LoadAcc: Invalid Parameter"); 00453 goto UnlockAndFree; 00454 } 00455 00456 /* 00457 * Since the accelerator table is coming from a resource, each 00458 * element has an extra WORD of padding which we strip here 00459 * to conform with the public (and internal) ACCEL structure. 00460 */ 00461 paccelT = UserLocalAlloc(0, sizeof(ACCEL) * (nAccel + 1)); 00462 if (paccelT == NULL) { 00463 goto UnlockAndFree; 00464 } 00465 for (i = 0; i < nAccel + 1; i++) { 00466 paccelT[i] = paccel[i].accel; 00467 } 00468 00469 handle = NtUserCreateAcceleratorTable(paccelT, 00470 nAccel + 1); 00471 00472 UserLocalFree(paccelT); 00473 00474 /* 00475 * Add this handle/address to the global table so 00476 * we won't load it twice. 00477 */ 00478 if (handle != NULL) { 00479 AddAccResource(handle, paccel); 00480 } 00481 UnlockAndFree: 00482 00483 UNLOCKRESOURCE(hrl, hmod); 00484 } 00485 00486 FREERESOURCE(hrl, hmod); 00487 } 00488 } 00489 00490 return handle; 00491 } 00492 00493 /***************************************************************************\ 00494 * LoadAcceleratorsA (API) 00495 * LoadAcceleratorsW (API) 00496 * 00497 * 00498 * 24-Sep-1990 MikeKe From Win30 00499 \***************************************************************************/ 00500 00501 HACCEL WINAPI LoadAcceleratorsA( 00502 HINSTANCE hmod, 00503 LPCSTR lpAccName) 00504 { 00505 HANDLE hRes; 00506 00507 hRes = FINDRESOURCEA((HANDLE)hmod, lpAccName, (LPSTR)RT_ACCELERATOR); 00508 00509 return (HACCEL)LoadAcc(hmod, hRes); 00510 } 00511 00512 HACCEL WINAPI LoadAcceleratorsW( 00513 HINSTANCE hmod, 00514 LPCWSTR lpAccName) 00515 { 00516 HANDLE hRes; 00517 00518 hRes = FINDRESOURCEW((HANDLE)hmod, lpAccName, RT_ACCELERATOR); 00519 00520 return (HACCEL)LoadAcc(hmod, hRes); 00521 } 00522 00523 /***************************************************************************\ 00524 * LoadStringA (API) 00525 * LoadStringW (API) 00526 * 00527 * 00528 * 05-Apr-1991 ScottLu Fixed to work with client/server. 00529 \***************************************************************************/ 00530 00531 int WINAPI LoadStringA( 00532 HINSTANCE hmod, 00533 UINT wID, 00534 LPSTR lpAnsiBuffer, 00535 int cchBufferMax) 00536 { 00537 LPWSTR lpUniBuffer; 00538 INT cchUnicode; 00539 INT cbAnsi = 0; 00540 00541 /* 00542 * LoadStringOrError appends a NULL but does not include it in the 00543 * return count-of-bytes 00544 */ 00545 cchUnicode = LoadStringOrError((HANDLE)hmod, 00546 wID, 00547 (LPWSTR)&lpUniBuffer, 00548 0, 00549 0); 00550 00551 if (cchUnicode) { 00552 00553 cbAnsi = WCSToMB(lpUniBuffer, 00554 cchUnicode, 00555 &lpAnsiBuffer, 00556 cchBufferMax - 1, 00557 FALSE); 00558 00559 cbAnsi = min(cbAnsi, cchBufferMax - 1); 00560 } 00561 00562 /* 00563 * Append a NULL but do not include it in the count returned 00564 */ 00565 lpAnsiBuffer[cbAnsi] = 0; 00566 return cbAnsi; 00567 } 00568 00569 int WINAPI LoadStringW( 00570 HINSTANCE hmod, 00571 UINT wID, 00572 LPWSTR lpBuffer, 00573 int cchBufferMax) 00574 { 00575 return LoadStringOrError((HANDLE)hmod, 00576 wID, 00577 lpBuffer, 00578 cchBufferMax, 00579 0); 00580 } 00581 00582 /***************************************************************************\ 00583 * SkipIDorString 00584 * 00585 * Skips string (or ID) and returns the next aligned WORD. 00586 * 00587 \***************************************************************************/ 00588 00589 PBYTE SkipIDorString( 00590 LPBYTE pb) 00591 { 00592 if (*((LPWORD)pb) == 0xFFFF) 00593 return (pb + 4); 00594 00595 while (*((PWCHAR)pb)++ != 0); 00596 00597 return pb; 00598 } 00599 00600 /***************************************************************************\ 00601 * GetSizeDialogTemplate 00602 * 00603 * This gets called by thank produced stubs. It returns the size of a 00604 * dialog template. 00605 * 00606 * 07-Apr-1991 ScottLu Created. 00607 \***************************************************************************/ 00608 00609 DWORD GetSizeDialogTemplate( 00610 HINSTANCE hmod, 00611 LPCDLGTEMPLATE pdt) 00612 { 00613 UINT cdit; 00614 LPBYTE pb; 00615 BOOL fChicago; 00616 LPDLGTEMPLATE2 pdt2; 00617 00618 if (HIWORD(pdt->style) == 0xFFFF) { 00619 00620 pdt2 = (LPDLGTEMPLATE2)pdt; 00621 fChicago = TRUE; 00622 00623 /* 00624 * Fail if the app is passing invalid style bits. 00625 */ 00626 if (pdt2->style & ~(DS_VALID40 | 0xffff0000)) { 00627 RIPMSG0(RIP_WARNING, "Bad dialog style bits - please remove"); 00628 return 0; 00629 } 00630 00631 pb = (LPBYTE)(((LPDLGTEMPLATE2)pdt) + 1); 00632 00633 } else { 00634 00635 fChicago = FALSE; 00636 00637 /* 00638 * Check if invalid style bits are being passed. Fail if the app 00639 * is a new app ( >= VER40). 00640 * This is to ensure that we are compatible with Chicago. 00641 */ 00642 if ((pdt->style & ~(DS_VALID40 | 0xffff0000)) && 00643 (GETEXPWINVER(hmod) >= VER40)) { 00644 00645 /* 00646 * It's a new app with invalid style bits - fail. 00647 */ 00648 RIPMSG0(RIP_WARNING, "Bad dialog style bits - please remove"); 00649 return 0; 00650 } 00651 00652 pb = (LPBYTE)(pdt + 1); 00653 } 00654 00655 /* 00656 * If there is a menu ordinal, add 4 bytes skip it. Otherwise it is a 00657 * string or just a 0. 00658 */ 00659 pb = SkipIDorString(pb); 00660 00661 /* 00662 * Skip window class and window text, adjust to next word boundary. 00663 */ 00664 pb = SkipIDorString(pb); 00665 pb = SkipIDorString(pb); 00666 00667 /* 00668 * Skip font type, size and name, adjust to next dword boundary. 00669 */ 00670 if ((fChicago ? pdt2->style : pdt->style) & DS_SETFONT) { 00671 pb += fChicago ? sizeof(DWORD) + sizeof(WORD): sizeof(WORD); 00672 pb = SkipIDorString(pb); 00673 } 00674 pb = (LPBYTE)(((ULONG_PTR)pb + 3) & ~3); 00675 00676 /* 00677 * Loop through dialog items now... 00678 */ 00679 cdit = fChicago ? pdt2->cDlgItems : pdt->cdit; 00680 00681 while (cdit-- != 0) { 00682 00683 UINT cbCreateParams; 00684 00685 pb += fChicago ? sizeof(DLGITEMTEMPLATE2) : sizeof(DLGITEMTEMPLATE); 00686 00687 /* 00688 * Skip the dialog control class name. 00689 */ 00690 pb = SkipIDorString(pb); 00691 00692 /* 00693 * Look at window text now. 00694 */ 00695 pb = SkipIDorString(pb); 00696 00697 cbCreateParams = *((LPWORD)pb); 00698 00699 /* 00700 * skip any CreateParams which include the generated size WORD. 00701 */ 00702 if (cbCreateParams) 00703 pb += cbCreateParams; 00704 00705 pb += sizeof(WORD); 00706 00707 /* 00708 * Point at the next dialog item. (DWORD aligned) 00709 */ 00710 pb = (LPBYTE)(((ULONG_PTR)pb + 3) & ~3); 00711 } 00712 00713 /* 00714 * Return template size. 00715 */ 00716 return (DWORD)(pb - (LPBYTE)pdt); 00717 } 00718 00719 /***************************************************************************\ 00720 * DialogBoxIndirectParamA (API) 00721 * DialogBoxIndirectParamW (API) 00722 * 00723 * Creates the dialog and goes into a modal loop processing input for it. 00724 * 00725 * 05-Apr-1991 ScottLu Created. 00726 \***************************************************************************/ 00727 00728 INT_PTR WINAPI DialogBoxIndirectParamA( 00729 HINSTANCE hmod, 00730 LPCDLGTEMPLATEA lpDlgTemplate, 00731 HWND hwndOwner, 00732 DLGPROC lpDialogFunc, 00733 LPARAM dwInitParam) 00734 { 00735 return DialogBoxIndirectParamAorW(hmod, 00736 (LPCDLGTEMPLATEW)lpDlgTemplate, 00737 hwndOwner, 00738 lpDialogFunc, 00739 dwInitParam, 00740 SCDLG_ANSI); 00741 } 00742 00743 INT_PTR WINAPI DialogBoxIndirectParamW( 00744 HINSTANCE hmod, 00745 LPCDLGTEMPLATEW lpDlgTemplate, 00746 HWND hwndOwner, 00747 DLGPROC lpDialogFunc, 00748 LPARAM dwInitParam) 00749 { 00750 return DialogBoxIndirectParamAorW(hmod, 00751 lpDlgTemplate, 00752 hwndOwner, 00753 lpDialogFunc, 00754 dwInitParam, 00755 0); 00756 } 00757 00758 INT_PTR WINAPI DialogBoxIndirectParamAorW( 00759 HINSTANCE hmod, 00760 LPCDLGTEMPLATEW lpDlgTemplate, 00761 HWND hwndOwner, 00762 DLGPROC lpDialogFunc, 00763 LPARAM dwInitParam, 00764 UINT fAnsiFlags) 00765 { 00766 DWORD cb; 00767 00768 /* 00769 * The server routine destroys the menu if it fails. 00770 */ 00771 cb = GetSizeDialogTemplate(hmod, lpDlgTemplate); 00772 00773 if (!cb) { 00774 RIPMSG0(RIP_WARNING, "DialogBoxIndirectParam: Invalid Paramter"); 00775 return -1; 00776 } 00777 00778 return InternalDialogBox(hmod, 00779 (LPDLGTEMPLATE)lpDlgTemplate, 00780 hwndOwner, 00781 lpDialogFunc, 00782 dwInitParam, 00783 SCDLG_CLIENT | (fAnsiFlags & (SCDLG_ANSI | SCDLG_16BIT))); 00784 } 00785 00786 /***************************************************************************\ 00787 * CreateDialogIndirectParamA (API) 00788 * CreateDialogIndirectParamW (API) 00789 * 00790 * Creates a dialog given a template and return s the window handle. 00791 * fAnsi determines if the dialog has an ANSI or UNICODE lpDialogFunc 00792 * 00793 * 05-Apr-1991 ScottLu Created. 00794 \***************************************************************************/ 00795 00796 HWND WINAPI CreateDialogIndirectParamA( 00797 HINSTANCE hmod, 00798 LPCDLGTEMPLATEA lpDlgTemplate, 00799 HWND hwndOwner, 00800 DLGPROC lpDialogFunc, 00801 LPARAM dwInitParam) 00802 { 00803 return CreateDialogIndirectParamAorW(hmod, 00804 (LPCDLGTEMPLATE)lpDlgTemplate, 00805 hwndOwner, 00806 lpDialogFunc, 00807 dwInitParam, 00808 SCDLG_ANSI); 00809 } 00810 00811 HWND WINAPI CreateDialogIndirectParamW( 00812 HINSTANCE hmod, 00813 LPCDLGTEMPLATEW lpDlgTemplate, 00814 HWND hwndOwner, 00815 DLGPROC lpDialogFunc, 00816 LPARAM dwInitParam) 00817 { 00818 return CreateDialogIndirectParamAorW(hmod, 00819 (LPCDLGTEMPLATE)lpDlgTemplate, 00820 hwndOwner, 00821 lpDialogFunc, 00822 dwInitParam, 00823 0); 00824 } 00825 00826 HWND WINAPI CreateDialogIndirectParamAorW( 00827 HANDLE hmod, 00828 LPCDLGTEMPLATE lpDlgTemplate, 00829 HWND hwndOwner, 00830 DLGPROC lpDialogFunc, 00831 LPARAM dwInitParam, 00832 UINT fAnsi) 00833 { 00834 DWORD cb; 00835 HWND hwndRet; 00836 00837 /* 00838 * The server routine destroys the menu if it fails. 00839 */ 00840 cb = GetSizeDialogTemplate(hmod, lpDlgTemplate); 00841 00842 if (!cb) { 00843 RIPMSG0(RIP_WARNING, "CreateDialogIndirect: Invalid Parameter"); 00844 return NULL; 00845 } 00846 00847 hwndRet = InternalCreateDialog(hmod, 00848 (LPDLGTEMPLATE)lpDlgTemplate, 00849 cb, 00850 hwndOwner, 00851 lpDialogFunc, 00852 dwInitParam, 00853 SCDLG_CLIENT | (fAnsi & (SCDLG_ANSI|SCDLG_16BIT))); 00854 00855 return hwndRet; 00856 } 00857 00858 /***************************************************************************\ 00859 * DialogBoxParamA (API) 00860 * DialogBoxParamW (API) 00861 * 00862 * Loads the resource, creates the dialog and goes into a modal loop processing 00863 * input for it. 00864 * 00865 * 05-Apr-1991 ScottLu Created. 00866 \***************************************************************************/ 00867 00868 INT_PTR WINAPI DialogBoxParamA( 00869 HINSTANCE hmod, 00870 LPCSTR lpName, 00871 HWND hwndOwner, 00872 DLGPROC lpDialogFunc, 00873 LPARAM dwInitParam) 00874 { 00875 HANDLE h; 00876 PVOID p; 00877 INT_PTR i = -1; 00878 00879 if (h = FINDRESOURCEA(hmod, (LPSTR)lpName, (LPSTR)RT_DIALOG)) { 00880 00881 if (h = LOADRESOURCE(hmod, h)) { 00882 00883 if (p = LOCKRESOURCE(h, hmod)) { 00884 00885 i = DialogBoxIndirectParamAorW(hmod, 00886 p, 00887 hwndOwner, 00888 lpDialogFunc, 00889 dwInitParam, 00890 SCDLG_ANSI); 00891 00892 UNLOCKRESOURCE(h, hmod); 00893 } 00894 00895 FREERESOURCE(h, hmod); 00896 } 00897 } 00898 00899 return i; 00900 } 00901 00902 INT_PTR WINAPI DialogBoxParamW( 00903 HINSTANCE hmod, 00904 LPCWSTR lpName, 00905 HWND hwndOwner, 00906 DLGPROC lpDialogFunc, 00907 LPARAM dwInitParam) 00908 { 00909 HANDLE h; 00910 PVOID p; 00911 INT_PTR i = -1; 00912 00913 UserAssert(LOWORD(hmod) == 0); // This should never be a WOW module 00914 00915 if (h = FINDRESOURCEW(hmod, lpName, RT_DIALOG)) { 00916 00917 if (p = LoadResource(hmod, h)) { 00918 00919 i = DialogBoxIndirectParamAorW(hmod, 00920 p, 00921 hwndOwner, 00922 lpDialogFunc, 00923 dwInitParam, 00924 0); 00925 } 00926 } 00927 00928 return i; 00929 } 00930 00931 /***************************************************************************\ 00932 * CreateDialogParamA (API) 00933 * CreateDialogParamW (API) 00934 * 00935 * Loads the resource, creates a dialog from that template, return s the 00936 * window handle. 00937 * 00938 * 05-Apr-1991 ScottLu Created. 00939 \***************************************************************************/ 00940 00941 HWND WINAPI CreateDialogParamA( 00942 HINSTANCE hmod, 00943 LPCSTR lpName, 00944 HWND hwndOwner, 00945 DLGPROC lpDialogFunc, 00946 LPARAM dwInitParam) 00947 { 00948 HANDLE h; 00949 LPDLGTEMPLATEA p; 00950 HWND hwnd = NULL; 00951 00952 if (h = FINDRESOURCEA(hmod, lpName, (LPSTR)RT_DIALOG)) { 00953 00954 if (h = LOADRESOURCE(hmod, h)) { 00955 00956 if (p = (LPDLGTEMPLATEA)LOCKRESOURCE(h, hmod)) { 00957 00958 hwnd = CreateDialogIndirectParamAorW(hmod, 00959 (LPCDLGTEMPLATE)p, 00960 hwndOwner, 00961 lpDialogFunc, 00962 dwInitParam, 00963 SCDLG_ANSI); 00964 00965 UNLOCKRESOURCE(h, hmod); 00966 } 00967 00968 FREERESOURCE(h, hmod); 00969 } 00970 } 00971 00972 return hwnd; 00973 } 00974 00975 HWND WINAPI CreateDialogParamW( 00976 HINSTANCE hmod, 00977 LPCWSTR lpName, 00978 HWND hwndOwner, 00979 DLGPROC lpDialogFunc, 00980 LPARAM dwInitParam) 00981 { 00982 HANDLE h; 00983 PVOID p; 00984 HWND hwnd = NULL; 00985 00986 if (h = FINDRESOURCEW(hmod, lpName, RT_DIALOG)) { 00987 00988 if (h = LOADRESOURCE(hmod, h)) { 00989 00990 if (p = LOCKRESOURCE(h, hmod)) { 00991 00992 hwnd = CreateDialogIndirectParamAorW(hmod, 00993 p, 00994 hwndOwner, 00995 lpDialogFunc, 00996 dwInitParam, 00997 0); 00998 00999 UNLOCKRESOURCE(h, hmod); 01000 } 01001 01002 FREERESOURCE(h, hmod); 01003 } 01004 } 01005 01006 return hwnd; 01007 } 01008 01009 /***************************************************************************\ 01010 * DestroyCursor (API) 01011 * 01012 * Client wrapper for NtUserDestroyCursor. 01013 * 01014 * 28-Nov-1994 JimA Created. 01015 \***************************************************************************/ 01016 01017 BOOL WINAPI DestroyCursor( 01018 HCURSOR hcur) 01019 { 01020 return NtUserDestroyCursor(hcur, CURSOR_CALLFROMCLIENT); 01021 } 01022 01023 /***************************************************************************\ 01024 * CreateIcoCur 01025 * 01026 * 01027 \***************************************************************************/ 01028 01029 HICON CreateIcoCur( 01030 PCURSORDATA lpi) 01031 { 01032 HCURSOR hcur; 01033 01034 UserAssert(lpi->hbmColor || lpi->hbmMask); 01035 01036 hcur = (HCURSOR)NtUserCallOneParam((lpi->CURSORF_flags & CURSORF_GLOBAL), 01037 SFI__CREATEEMPTYCURSOROBJECT); 01038 01039 if (hcur == NULL) 01040 return NULL; 01041 01042 #if DBG 01043 { 01044 BITMAP bmMask; 01045 BITMAP bmColor; 01046 01047 UserAssert(GetObject(lpi->hbmMask, sizeof(BITMAP), &bmMask)); 01048 01049 /* Bug 252902 - joejo 01050 * Since the width and height of the mask bitmap is set below 01051 * we really don't need to assert on the width/height check. Throwing 01052 * a warning should be good enough. 01053 */ 01054 if (bmMask.bmWidth != (LONG)lpi->cx) { 01055 RIPMSG1(RIP_WARNING, "Mask width not equal to requested width: lpi %#p", lpi); 01056 } 01057 01058 if (bmMask.bmHeight != (LONG)lpi->cy) { 01059 RIPMSG1(RIP_WARNING, "Mask height not equal to requested height: lpi %#p", lpi); 01060 } 01061 01062 if (lpi->hbmColor) { 01063 UserAssert(GetObject(lpi->hbmColor, sizeof(BITMAP), &bmColor)); 01064 UserAssert(bmMask.bmHeight == bmColor.bmHeight * 2); 01065 UserAssert(bmMask.bmWidth == bmColor.bmWidth); 01066 } 01067 } 01068 #endif 01069 01070 if (_SetCursorIconData(hcur, lpi)) 01071 return hcur; 01072 01073 NtUserDestroyCursor(hcur, CURSOR_ALWAYSDESTROY); 01074 01075 return NULL; 01076 } 01077 01078 /***************************************************************************\ 01079 * CreateIcoCurIndirect 01080 * 01081 * 01082 \***************************************************************************/ 01083 01084 HCURSOR CreateIcoCurIndirect( 01085 PCURSORDATA pcurCreate, 01086 UINT cPlanes, 01087 UINT cBitsPixel, 01088 CONST BYTE *lpANDbits, 01089 CONST BYTE *lpXORbits) 01090 { 01091 int cbBits; 01092 HCURSOR hcurNew; 01093 BOOL bColor; 01094 UINT cx; 01095 UINT cy; 01096 LPBYTE pBits = NULL; 01097 01098 /* 01099 * Allocate CURSOR structure. 01100 */ 01101 hcurNew = (HCURSOR)NtUserCallOneParam(0, SFI__CREATEEMPTYCURSOROBJECT); 01102 01103 if (hcurNew == NULL) 01104 return NULL; 01105 01106 /* 01107 * If there is no Color bitmap, create a single buffer that contains both 01108 * the AND and XOR bits. The AND bitmap is always MonoChrome 01109 */ 01110 bColor = (cPlanes | cBitsPixel) > 1; 01111 01112 if (!bColor) { 01113 01114 cbBits = (((pcurCreate->cx + 0x0F) & ~0x0F) >> 3) * pcurCreate->cy; 01115 01116 pBits = (LPBYTE)UserLocalAlloc(HEAP_ZERO_MEMORY, (cbBits * 2)); 01117 01118 if (pBits == NULL) { 01119 NtUserDestroyCursor(hcurNew, CURSOR_ALWAYSDESTROY); 01120 return NULL; 01121 } 01122 01123 RtlCopyMemory(pBits, lpANDbits, cbBits); 01124 RtlCopyMemory(pBits + cbBits, lpXORbits, cbBits); 01125 lpANDbits = pBits; 01126 } 01127 01128 /* 01129 * Create hbmMask (its always MonoChrome) 01130 */ 01131 cx = pcurCreate->cx; 01132 cy = pcurCreate->cy * 2; 01133 01134 pcurCreate->hbmMask = CreateBitmap(cx, cy, 1, 1, lpANDbits); 01135 01136 if (pcurCreate->hbmMask == NULL) { 01137 01138 /* 01139 * If this is a COLOR icon/cursor, lpANDBits doesn't need to be 01140 * pcurCreate->cy * 2; indeed, we don't use this double height at all. 01141 * This is a bug that will be fixed post 4.0. 01142 * For now, let's try to handle the case where the CreateBitmap call 01143 * failed because the caller didn't pass in a double height AND mask 01144 * (Win95 doesn't have this bug) 01145 */ 01146 if (bColor) { 01147 01148 RIPMSG0(RIP_WARNING, "CreateIcoCurIndirect: Retrying hbmMask creation."); 01149 01150 cbBits = (((pcurCreate->cx + 0x0F) & ~0x0F) >> 3) * pcurCreate->cy; 01151 pBits = (LPBYTE)UserLocalAlloc(HEAP_ZERO_MEMORY, cbBits*2); 01152 01153 if (pBits == NULL) { 01154 NtUserDestroyCursor(hcurNew, CURSOR_ALWAYSDESTROY); 01155 return NULL; 01156 } 01157 01158 RtlCopyMemory(pBits, lpANDbits, cbBits); 01159 pcurCreate->hbmMask = CreateBitmap(cx, cy, 1, 1, pBits); 01160 UserLocalFree(pBits); 01161 01162 pBits = NULL; 01163 } 01164 01165 if (pcurCreate->hbmMask == NULL) { 01166 01167 /* 01168 * CreateBitmap() failed. Clean-up and get out of here. 01169 */ 01170 NtUserDestroyCursor(hcurNew, CURSOR_ALWAYSDESTROY); 01171 01172 if (pBits != NULL) 01173 UserLocalFree(pBits); 01174 01175 return NULL; 01176 } 01177 } 01178 01179 /* 01180 * Create hbmColor or NULL it so that CallOEMCursor doesn't think we are 01181 * color. 01182 */ 01183 if (bColor) { 01184 pcurCreate->hbmColor = CreateBitmap(cx, 01185 cy / 2, 01186 cPlanes, 01187 cBitsPixel, 01188 lpXORbits); 01189 01190 if (pcurCreate->hbmColor == NULL) { 01191 01192 /* 01193 * CreateBitmap() failed. Clean-up and get out of here. 01194 */ 01195 DeleteObject(pcurCreate->hbmMask); 01196 NtUserDestroyCursor(hcurNew, CURSOR_ALWAYSDESTROY); 01197 return NULL; 01198 } 01199 01200 pcurCreate->bpp = (cPlanes * cBitsPixel); 01201 01202 } else { 01203 pcurCreate->hbmColor = NULL; 01204 pcurCreate->bpp = 1; 01205 } 01206 01207 /* 01208 * Load contents into the cursor/icon object 01209 */ 01210 pcurCreate->cy = cy; 01211 pcurCreate->lpModName = NULL; 01212 pcurCreate->lpName = NULL; 01213 pcurCreate->rt = 0; 01214 pcurCreate->CURSORF_flags = 0; 01215 01216 if (_SetCursorIconData(hcurNew, pcurCreate)) { 01217 if (pBits != NULL) 01218 UserLocalFree(pBits); 01219 return hcurNew; 01220 } 01221 01222 /* 01223 * Could not set up cursor/icon, so free resources. 01224 */ 01225 NtUserDestroyCursor(hcurNew, CURSOR_ALWAYSDESTROY); 01226 DeleteObject(pcurCreate->hbmMask); 01227 01228 if (pcurCreate->hbmColor) 01229 DeleteObject(pcurCreate->hbmColor); 01230 if (pBits != NULL) 01231 UserLocalFree(pBits); 01232 01233 return NULL; 01234 } 01235 01236 /***************************************************************************\ 01237 * CreateCursor (API) 01238 * 01239 * History: 01240 * 26-Feb-1991 MikeKe Created. 01241 * 01-Aug-1991 IanJa Init cur.pszModname or DestroyCursor will work 01242 \***************************************************************************/ 01243 01244 HCURSOR WINAPI CreateCursor( 01245 HINSTANCE hModule, 01246 int iXhotspot, 01247 int iYhotspot, 01248 int iWidth, 01249 int iHeight, 01250 LPBYTE lpANDplane, 01251 LPBYTE lpXORplane) 01252 { 01253 CURSORDATA cur; 01254 UNREFERENCED_PARAMETER(hModule); 01255 01256 if ((iXhotspot < 0) || (iXhotspot > iWidth) || 01257 (iYhotspot < 0) || (iYhotspot > iHeight)) { 01258 return 0; 01259 } 01260 01261 RtlZeroMemory(&cur, sizeof(cur)); 01262 cur.xHotspot = (SHORT)iXhotspot; 01263 cur.yHotspot = (SHORT)iYhotspot; 01264 cur.cx = (DWORD)iWidth; 01265 cur.cy = (DWORD)iHeight; 01266 01267 return CreateIcoCurIndirect(&cur, 1, 1, lpANDplane, lpXORplane); 01268 } 01269 01270 /***************************************************************************\ 01271 * CreateIcon (API) 01272 * 01273 * History: 01274 * 26-Feb-1991 MikeKe Created. 01275 * 01-Aug-1991 IanJa Init cur.pszModname so DestroyIcon will work 01276 \***************************************************************************/ 01277 01278 HICON WINAPI CreateIcon( 01279 HINSTANCE hModule, 01280 int iWidth, 01281 int iHeight, 01282 BYTE planes, 01283 BYTE bpp, 01284 CONST BYTE *lpANDplane, 01285 CONST BYTE *lpXORplane) 01286 { 01287 CURSORDATA cur; 01288 UNREFERENCED_PARAMETER(hModule); 01289 01290 RtlZeroMemory(&cur, sizeof(cur)); 01291 cur.xHotspot = (SHORT)(iWidth / 2); 01292 cur.yHotspot = (SHORT)(iHeight / 2); 01293 cur.cx = (DWORD)iWidth; 01294 cur.cy = (DWORD)iHeight; 01295 01296 return CreateIcoCurIndirect(&cur, planes, bpp, lpANDplane, lpXORplane); 01297 } 01298 01299 /***************************************************************************\ 01300 * CreateIconIndirect (API) 01301 * 01302 * Creates an icon or cursor from an ICONINFO structure. Does not destroy 01303 * cursor/icon bitmaps. 01304 * 01305 * 24-Jul-1991 ScottLu Created. 01306 \***************************************************************************/ 01307 HICON WINAPI CreateIconIndirect( 01308 PICONINFO piconinfo) 01309 { 01310 HCURSOR hcur; 01311 CURSORDATA cur; 01312 BITMAP bmMask; 01313 BITMAP bmColor; 01314 HBITMAP hbmpBits2, hbmpMem; 01315 HDC hdcMem; 01316 01317 /* 01318 * Make sure the bitmaps are real, and get their dimensions. 01319 */ 01320 if (!GetObjectW(piconinfo->hbmMask, sizeof(BITMAP), &bmMask)) 01321 return NULL; 01322 01323 if (piconinfo->hbmColor != NULL) { 01324 if (!GetObjectW(piconinfo->hbmColor, sizeof(BITMAP), &bmColor)) 01325 return NULL; 01326 } 01327 01328 /* 01329 * Allocate CURSOR structure. 01330 */ 01331 hcur = (HCURSOR)NtUserCallOneParam(0, SFI__CREATEEMPTYCURSOROBJECT); 01332 if (hcur == NULL) 01333 return NULL; 01334 01335 /* 01336 * Internally, USER stores the height as 2 icons high - because when 01337 * loading bits from a resource, in both b/w and color icons, the 01338 * bits are stored on top of one another (AND/XOR mask, AND/COLOR bitmap). 01339 * When bitmaps are passed in to CreateIconIndirect(), they are passed 01340 * as two bitmaps in the color case, and one bitmap (with the stacked 01341 * masks) in the black and white case. Adjust cur.cy so it is 2 icons 01342 * high in both cases. 01343 */ 01344 01345 RtlZeroMemory(&cur, sizeof(cur)); 01346 cur.cx = bmMask.bmWidth; 01347 01348 if (piconinfo->hbmColor == NULL) { 01349 01350 cur.cy = bmMask.bmHeight; 01351 cur.bpp = 1; 01352 01353 } else { 01354 cur.cy = bmMask.bmHeight * 2; 01355 cur.bpp = (DWORD)(bmColor.bmBitsPixel * bmColor.bmPlanes); 01356 cur.hbmColor = CopyBmp(piconinfo->hbmColor, 0, 0, LR_DEFAULTCOLOR); 01357 01358 if (cur.hbmColor == NULL) { 01359 RIPMSG0(RIP_WARNING, "CreateIconIndirect: Failed to copy piconinfo->hbmColor"); 01360 goto CleanUp; 01361 } 01362 } 01363 01364 /* 01365 * hbmMask must always be double height, even for color icons. 01366 * So cy might be equal to bmMask.bmHeight * 2 at this point. 01367 * If this is the case, the second half of hbmMask won't be initilized; 01368 * nobody is supposed to use it but GDI expects it there when checking the 01369 * bitmap dimensions (for cursors) 01370 */ 01371 cur.hbmMask = CreateBitmap(cur.cx, cur.cy, 1, 1, NULL); 01372 01373 if (cur.hbmMask == NULL) { 01374 RIPMSG0(RIP_WARNING, "CreateIconIndirect: Failed to create cur.hbmMask"); 01375 goto CleanUp; 01376 } 01377 01378 RtlEnterCriticalSection(&gcsHdc); 01379 01380 01381 if (hdcMem = CreateCompatibleDC (ghdcBits2)) { 01382 01383 hbmpMem = SelectObject(hdcMem, cur.hbmMask); 01384 hbmpBits2 = SelectObject(ghdcBits2, piconinfo->hbmMask); 01385 01386 BitBlt(hdcMem, 01387 0, 01388 0, 01389 bmMask.bmWidth, 01390 bmMask.bmHeight, 01391 ghdcBits2, 01392 0, 01393 0, 01394 SRCCOPY); 01395 01396 SelectObject(hdcMem, hbmpMem); 01397 SelectObject(ghdcBits2, hbmpBits2); 01398 DeleteDC (hdcMem); 01399 01400 } else { 01401 01402 RtlLeaveCriticalSection(&gcsHdc); 01403 RIPMSG0(RIP_WARNING, "CreateIconIndirect: CreateCompatibleDC failed"); 01404 goto CleanUp; 01405 } 01406 01407 RtlLeaveCriticalSection(&gcsHdc); 01408 01409 /* 01410 * rt and Hotspot 01411 */ 01412 if (piconinfo->fIcon) { 01413 cur.rt = PTR_TO_ID(RT_ICON); 01414 cur.xHotspot = (SHORT)(cur.cx / 2); 01415 cur.yHotspot = (SHORT)(cur.cy / 4); 01416 } else { 01417 cur.rt = PTR_TO_ID(RT_CURSOR); 01418 cur.xHotspot = ((SHORT)piconinfo->xHotspot); 01419 cur.yHotspot = ((SHORT)piconinfo->yHotspot); 01420 } 01421 01422 01423 if (_SetCursorIconData(hcur, &cur)) { 01424 return hcur; 01425 } 01426 01427 CleanUp: 01428 /* 01429 * Note that if this fails, the bitmaps have NOT been made public. 01430 */ 01431 if (cur.hbmMask != NULL) { 01432 DeleteObject(cur.hbmMask); 01433 } 01434 if (cur.hbmColor != NULL) { 01435 DeleteObject(cur.hbmColor); 01436 } 01437 01438 NtUserDestroyCursor(hcur, CURSOR_ALWAYSDESTROY); 01439 return NULL; 01440 } 01441 01442 /***************************************************************************\ 01443 * GetIconInfo (API) 01444 * 01445 * Returns icon information, including bitmaps. 01446 * 01447 * 24-Jul-1991 ScottLu Created. 01448 \***************************************************************************/ 01449 01450 BOOL WINAPI GetIconInfo( 01451 HICON hicon, 01452 PICONINFO piconinfo) 01453 { 01454 return NtUserGetIconInfo(hicon, piconinfo, NULL, NULL, NULL, FALSE); 01455 } 01456 01457 /***************************************************************************\ 01458 * GetCursorFrameInfo (API) 01459 * 01460 * Returns cursor information. 01461 * 01462 * 24-Jul-1991 ScottLu Created. 01463 \***************************************************************************/ 01464 01465 HCURSOR WINAPI GetCursorFrameInfo( 01466 HCURSOR hcur, 01467 LPWSTR lpName, 01468 int iFrame, 01469 LPDWORD pjifRate, 01470 LPINT pccur) 01471 { 01472 /* 01473 * Caller wants us to return the version of this cursor that is stored 01474 * in the display driver. 01475 */ 01476 if (hcur == NULL) { 01477 01478 return LoadIcoCur(NULL, 01479 lpName, 01480 RT_CURSOR, 01481 0, 01482 0, 01483 LR_DEFAULTSIZE); 01484 } 01485 01486 return NtUserGetCursorFrameInfo(hcur, iFrame, pjifRate, pccur); 01487 } 01488 01489 /***************************************************************************\ 01490 * _FreeResource (API) 01491 * _LockResource (API) 01492 * _UnlockResource (API) 01493 * 01494 * These are dummy routines that need to exist for the apfnResCallNative 01495 * array, which is used when calling the run-time libraries. 01496 * 01497 \***************************************************************************/ 01498 01499 BOOL WINAPI _FreeResource( 01500 HANDLE hResData, 01501 HINSTANCE hModule) 01502 { 01503 UNREFERENCED_PARAMETER(hResData); 01504 UNREFERENCED_PARAMETER(hModule); 01505 01506 return FALSE; 01507 } 01508 01509 LPSTR WINAPI _LockResource( 01510 HANDLE hResData, 01511 HINSTANCE hModule) 01512 { 01513 UNREFERENCED_PARAMETER(hModule); 01514 01515 return (LPSTR)(hResData); 01516 } 01517 01518 BOOL WINAPI _UnlockResource( 01519 HANDLE hResData, 01520 HINSTANCE hModule) 01521 { 01522 UNREFERENCED_PARAMETER(hResData); 01523 UNREFERENCED_PARAMETER(hModule); 01524 01525 return TRUE; 01526 } 01527 01528 /***************************************************************************\ 01529 * LookupIconIdFromDirectory (API) 01530 * 01531 * This searches through an icon directory for the icon that best fits the 01532 * current display device. 01533 * 01534 * 24-07-1991 ScottLu Created. 01535 \***************************************************************************/ 01536 01537 int WINAPI LookupIconIdFromDirectory( 01538 PBYTE presbits, 01539 BOOL fIcon) 01540 { 01541 return LookupIconIdFromDirectoryEx(presbits, fIcon, 0, 0, 0); 01542 } 01543 01544 /***************************************************************************\ 01545 * LookupIconIdFromDirectoryEx (API) 01546 * 01547 * 01548 \***************************************************************************/ 01549 01550 int WINAPI LookupIconIdFromDirectoryEx( 01551 PBYTE presbits, 01552 BOOL fIcon, 01553 int cxDesired, 01554 int cyDesired, 01555 UINT LR_flags) 01556 { 01557 ConnectIfNecessary(); 01558 01559 return RtlGetIdFromDirectory(presbits, 01560 fIcon, 01561 cxDesired, 01562 cyDesired, 01563 LR_flags, 01564 NULL); 01565 } 01566 /***************************************************************************\ 01567 * LoadCursorIconFromResource (API) 01568 * 01569 * Loads animated icon/cursor from a pointer to a resource 01570 * 01571 * 02-20-1996 GerardoB Created. 01572 \***************************************************************************/ 01573 HANDLE LoadCursorIconFromResource( 01574 PBYTE presbits, 01575 LPCWSTR lpName, 01576 int cxDesired, 01577 int cyDesired, 01578 UINT LR_flags) 01579 { 01580 BOOL fAni; 01581 FILEINFO fi; 01582 LPWSTR lpwszRT; 01583 01584 fi.pFileMap = presbits; 01585 fi.pFilePtr = fi.pFileMap; 01586 fi.pFileEnd = fi.pFileMap + sizeof (RTAG) + ((RTAG *)presbits)->ckSize; 01587 fi.pszName = lpName; 01588 01589 return LoadCursorIconFromFileMap(&fi, 01590 &lpwszRT, 01591 cxDesired, 01592 cyDesired, 01593 LR_flags, 01594 &fAni); 01595 } 01596 /***************************************************************************\ 01597 * CreateIconFromResource (API) 01598 * 01599 * Takes resource bits and creates either an icon or cursor. 01600 * 01601 * 24-07-1991 ScottLu Created. 01602 \***************************************************************************/ 01603 01604 HICON WINAPI CreateIconFromResource( 01605 PBYTE presbits, 01606 DWORD dwResSize, 01607 BOOL fIcon, 01608 DWORD dwVer) 01609 { 01610 return CreateIconFromResourceEx(presbits, 01611 dwResSize, 01612 fIcon, 01613 dwVer, 01614 0, 01615 0, 01616 LR_DEFAULTSIZE | LR_SHARED); 01617 } 01618 01619 /***************************************************************************\ 01620 * CreateIconFromResourceEx (API) 01621 * 01622 * Takes resource bits and creates either an icon or cursor. 01623 * 01624 * 30-Aug-1994 FritzS Created 01625 \***************************************************************************/ 01626 01627 HICON WINAPI CreateIconFromResourceEx( 01628 PBYTE presbits, 01629 DWORD dwResSize, 01630 BOOL fIcon, 01631 DWORD dwVer, 01632 int cxDesired, 01633 int cyDesired, 01634 UINT LR_flags) 01635 { 01636 UNREFERENCED_PARAMETER(dwResSize); 01637 01638 /* 01639 * NT Specific code to validate the version. 01640 */ 01641 if ((dwVer < 0x00020000) || (dwVer > 0x00030000)) { 01642 RIPMSG0(RIP_WARNING, "CreateIconFromResourceEx: Invalid Paramter"); 01643 return NULL; 01644 } 01645 01646 /* 01647 * Set desired size of resource based on flags and/or true 01648 * dimensions passed in. 01649 */ 01650 cxDesired = GetIcoCurWidth(cxDesired , fIcon, LR_flags, 0); 01651 cyDesired = GetIcoCurHeight(cyDesired, fIcon, LR_flags, 0); 01652 01653 if (ISRIFFFORMAT(presbits)) { 01654 return LoadCursorIconFromResource (presbits, NULL, cxDesired, cyDesired, LR_flags); 01655 } else { 01656 return ConvertDIBIcon((LPBITMAPINFOHEADER)presbits, 01657 NULL, 01658 NULL, 01659 fIcon, 01660 cxDesired, 01661 cyDesired, 01662 LR_flags); 01663 } 01664 } 01665 01666 /***************************************************************************\ 01667 * Convert1BppToMonoBitmap 01668 * 01669 * This routine converts a 1bpp bitmap to a true monochrome surface. This 01670 * is done for bitmaps which need to do foreground/background color matching 01671 * at output time. Otherwise, a 1bpp will just match to its palette. 01672 * 01673 * NOTE: This routine deletes the original bitmap if successful. If failure 01674 * we'll return the original bitmap. 01675 * 01676 * History: 01677 * 17-Apr-1996 ChrisWil Created 01678 \***************************************************************************/ 01679 01680 HBITMAP Convert1BppToMonoBitmap( 01681 HDC hdcSrc, 01682 HBITMAP hbm1Bpp) 01683 { 01684 HBITMAP hbmMono = hbm1Bpp; 01685 HBITMAP hbmDst; 01686 HBITMAP hbmS; 01687 HBITMAP hbmD; 01688 HDC hdcDst; 01689 BITMAP bm; 01690 01691 if (hdcDst = CreateCompatibleDC(hdcSrc)) { 01692 01693 GetObject(hbm1Bpp, sizeof(BITMAP), &bm); 01694 01695 if (hbmDst = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL)) { 01696 01697 hbmS = SelectBitmap(hdcSrc, hbm1Bpp); 01698 hbmD = SelectBitmap(hdcDst, hbmDst); 01699 01700 BitBlt(hdcDst, 01701 0, 01702 0, 01703 bm.bmWidth, 01704 bm.bmHeight, 01705 hdcSrc, 01706 0, 01707 0, 01708 SRCCOPY); 01709 01710 SelectBitmap(hdcSrc, hbmS); 01711 SelectBitmap(hdcDst, hbmD); 01712 01713 hbmMono = hbmDst; 01714 DeleteObject(hbm1Bpp); 01715 } 01716 01717 DeleteDC(hdcDst); 01718 } 01719 01720 return hbmMono; 01721 } 01722 01723 /***************************************************************************\ 01724 * CreateScreenBitmap 01725 * 01726 * This routine creates a screen bitmap. We use the CreateDIBitmap call 01727 * to do compatible color-matching with Win95. Also, note that this 01728 * routine takes in WORD aligned bits. 01729 * 01730 \***************************************************************************/ 01731 01732 HBITMAP CreateScreenBitmap( 01733 int cx, 01734 int cy, 01735 UINT planes, 01736 UINT bpp, 01737 LPSTR lpBits, 01738 LPBOOL pf1Bpp) 01739 { 01740 HDC hdcScreen; 01741 HBITMAP hbm = NULL; 01742 DWORD dwCount; 01743 01744 static struct { 01745 BITMAPINFOHEADER bi; 01746 DWORD ct[16]; 01747 } dib4Vga = {{sizeof(BITMAPINFOHEADER), 01748 0, 01749 0, 01750 1, 01751 4, 01752 BI_RGB, 01753 0, 01754 0, 01755 0, 01756 16, 01757 0 01758 }, 01759 {0x00000000, 01760 0x00800000, 01761 0x00008000, 01762 0x00808000, 01763 0x00000080, 01764 0x00800080, 01765 0x00008080, 01766 0x00C0C0C0, 01767 0x00808080, 01768 0x00FF0000, 01769 0x0000FF00, 01770 0x00FFFF00, 01771 0x000000FF, 01772 0x00FF00FF, 01773 0x0000FFFF, 01774 0x00FFFFFF 01775 } 01776 }; 01777 01778 static struct { 01779 BITMAPINFOHEADER bi; 01780 DWORD ct[2]; 01781 } dib1Vga = {{sizeof(BITMAPINFOHEADER), 01782 0, 01783 0, 01784 1, 01785 1, 01786 BI_RGB, 01787 0, 01788 0, 01789 0, 01790 2, 01791 0 01792 }, 01793 {0x00000000, 01794 0x00FFFFFF 01795 } 01796 }; 01797 01798 01799 /* 01800 * Create the surface. 01801 */ 01802 if (hdcScreen = GETINITDC()) { 01803 01804 /* 01805 * This appears to mess up color to mono conversion by losing all 01806 * the data and forcing all non-forground colors to black. 01807 * (try copyimage with IDC_WARNING_DEFAULT) 01808 * This is what win95 does but their system works. The scary thing 01809 * (according to marke) is that win95 may have changed GDI to make 01810 * this work. 01811 * 01812 * In order to get nearest-color-matching compatible with Win95, 01813 * we're going to need to use the CreateDIBitmap() for mono-surfaces. 01814 * This code-path will do nearest-color, rather than color-matching. 01815 */ 01816 if ((bpp == 1) && (planes == 1)) { 01817 01818 dib1Vga.bi.biWidth = cx; 01819 dib1Vga.bi.biHeight = cy; 01820 01821 hbm = CreateDIBitmap(hdcScreen, 01822 (LPBITMAPINFOHEADER)&dib1Vga, 01823 CBM_CREATEDIB, 01824 NULL, 01825 (LPBITMAPINFO)&dib1Vga, 01826 DIB_RGB_COLORS); 01827 01828 *pf1Bpp = TRUE; 01829 01830 } else { 01831 01832 if (((planes == 0) || (planes == gpsi->Planes)) && 01833 ((bpp == 0) || (bpp == gpsi->BitsPixel))) { 01834 01835 hbm = CreateCompatibleBitmap(hdcScreen, cx, cy); 01836 01837 } else { 01838 01839 dib4Vga.bi.biBitCount = planes * bpp ? planes * bpp : gpsi->BitCount; 01840 01841 #if 0 // We use to do the dib-section create, but this breaks icons 01842 // when they are made public (can't make a dibsection public). So 01843 // we now wil create this as a real-dib. 01844 // 01845 { 01846 DWORD dwDummy; 01847 01848 dib4Vga.bi.biWidth = cx; 01849 dib4Vga.bi.biHeight = -cy; // top-down DIB (like a DDB) 01850 01851 hbm = CreateDIBSection(hdcScreen, 01852 (LPBITMAPINFO)&dib4Vga, 01853 DIB_RGB_COLORS, 01854 (LPVOID)&dwDummy, 01855 0, 01856 0); 01857 } 01858 #else 01859 dib4Vga.bi.biWidth = cx; 01860 dib4Vga.bi.biHeight = cy; 01861 01862 hbm = CreateDIBitmap(hdcScreen, 01863 (LPBITMAPINFOHEADER)&dib4Vga, 01864 CBM_CREATEDIB, 01865 NULL, 01866 (LPBITMAPINFO)&dib4Vga, 01867 DIB_RGB_COLORS); 01868 #endif 01869 } 01870 } 01871 01872 RELEASEINITDC(hdcScreen); 01873 } 01874 01875 if (hbm && lpBits) { 01876 01877 BITMAP bm; 01878 01879 GetObject(hbm, sizeof(BITMAP), &bm); 01880 dwCount = (DWORD)(UINT)(bm.bmWidthBytes * bm.bmPlanes) * (DWORD)(UINT)cy; 01881 SetBitmapBits(hbm, dwCount, lpBits); 01882 } 01883 01884 return hbm; 01885 } 01886 01887 /***************************************************************************\ 01888 * LoadBmp (Worker) 01889 * 01890 * This routine decides whether the bitmap to be loaded is in old or new (DIB) 01891 * format and calls appropriate handlers. 01892 * 01893 * History: 01894 * 24-Sep-1990 MikeKe From Win30. 01895 * 18-Jun-1991 ChuckWh Added local bitmap handle support. 01896 * 05-Sep-1995 ChrisWil Port/Change for Chicago functionality. 01897 \***************************************************************************/ 01898 01899 HBITMAP LoadBmp( 01900 HINSTANCE hmod, 01901 LPCWSTR lpName, 01902 int cxDesired, 01903 int cyDesired, 01904 UINT flags) 01905 { 01906 HBITMAP hbmp = NULL; 01907 BOOL fFree = FALSE; 01908 BOOL f1Bpp = FALSE; 01909 01910 /***************************************************************************\ 01911 * Bitmap Resource Table 01912 * 01913 * As of WIN4.0, most system bitmaps are rendered instead of grabbed from the 01914 * display driver. However, a lot of apps, especially those that fake their 01915 * own MDI, do LoadBitmap(NULL, OBM_...) to grab a system bitmap. So we 01916 * hook those requests here and copy our rendered bitmaps into a newly- 01917 * created bitmap. Note that this is actually faster than loading from a 01918 * resource table! 01919 * 01920 * BOGUS -- give 'em old close buttons, not new cool X's 01921 * 01922 \***************************************************************************/ 01923 #define MAX_BMPMAP 32 01924 01925 CONST static MAPRES MapOemBmp[MAX_BMPMAP] = { 01926 01927 {OBM_BTNCORNERS , OBI_RADIOMASK , }, 01928 {OBM_BTSIZE , OBI_NCGRIP , }, 01929 {OBM_CHECK , OBI_MENUCHECK , MR_MONOCHROME }, 01930 {OBM_CHECKBOXES , OBI_CHECK , }, 01931 {OBM_COMBO , OBI_DNARROW , }, 01932 {OBM_DNARROW , OBI_DNARROW , }, 01933 {OBM_DNARROWD , OBI_DNARROW_D , }, 01934 {OBM_DNARROWI , OBI_DNARROW_I , }, 01935 {OBM_LFARROW , OBI_LFARROW , }, 01936 {OBM_LFARROWD , OBI_LFARROW_D , }, 01937 {OBM_LFARROWI , OBI_LFARROW_I , }, 01938 01939 /* 01940 * Use MONO bitmaps in future once flat/mono controls are worked out. 01941 */ 01942 {OBM_OLD_DNARROW, OBI_DNARROW , MR_FAILFOR40 }, 01943 {OBM_OLD_LFARROW, OBI_LFARROW , MR_FAILFOR40 }, 01944 {OBM_OLD_REDUCE , OBI_REDUCE_MBAR , MR_FAILFOR40 }, 01945 {OBM_OLD_RESTORE, OBI_RESTORE_MBAR , MR_FAILFOR40 }, 01946 {OBM_OLD_RGARROW, OBI_RGARROW , MR_FAILFOR40 }, 01947 {OBM_OLD_UPARROW, OBI_UPARROW , MR_FAILFOR40 }, 01948 {OBM_OLD_ZOOM , OBI_ZOOM , MR_FAILFOR40 }, 01949 01950 {OBM_MNARROW , OBI_MENUARROW , MR_MONOCHROME }, 01951 {OBM_REDUCE , OBI_REDUCE_MBAR , }, 01952 {OBM_REDUCED , OBI_REDUCE_MBAR_D , }, 01953 {OBM_RESTORE , OBI_RESTORE_MBAR , }, 01954 {OBM_RESTORED , OBI_RESTORE_MBAR_D , }, 01955 {OBM_RGARROW , OBI_RGARROW , }, 01956 {OBM_RGARROWD , OBI_RGARROW_D , }, 01957 {OBM_RGARROWI , OBI_RGARROW_I , }, 01958 {OBM_SIZE , OBI_NCGRIP , }, 01959 {OBM_UPARROW , OBI_UPARROW , }, 01960 {OBM_UPARROWD , OBI_UPARROW_D , }, 01961 {OBM_UPARROWI , OBI_UPARROW_I , }, 01962 {OBM_ZOOM , OBI_ZOOM , }, 01963 {OBM_ZOOMD , OBI_ZOOM_D , } 01964 }; 01965 01966 01967 /* 01968 * If hmod is valid, load the client-side bits. 01969 */ 01970 if (hmod == NULL) { 01971 01972 HBITMAP hOldBmp; 01973 WORD bm; 01974 WORD wID; 01975 BOOL fCombo; 01976 BOOL fCheckBoxes; 01977 int i; 01978 RECT rc; 01979 BOOL fSysMenu = FALSE; 01980 BOOL fMenu = FALSE; 01981 BOOL fMono = FALSE; 01982 01983 hmod = hmodUser; 01984 01985 /* 01986 * Since the resource is coming from USER32, we only 01987 * deal with ID types. 01988 */ 01989 wID = PTR_TO_ID(lpName); 01990 01991 switch(wID) { 01992 case OBM_OLD_CLOSE: 01993 if (GETAPPVER() >= VER40) 01994 goto FailOldLoad; 01995 01996 /* 01997 * fall through to the Close case. 01998 */ 01999 02000 case OBM_CLOSE: 02001 /* the new look for the system menu is to use the window's 02002 * class icon -- but since here we don't know which window 02003 * they'll be using this for, fall back on the good ole' 02004 * windows logo icon 02005 */ 02006 cxDesired = (SYSMET(CXMENUSIZE) + SYSMET(CXEDGE)) * 2; 02007 cyDesired = SYSMET(CYMENUSIZE) + (2 * SYSMET(CYEDGE)); 02008 fSysMenu = TRUE; 02009 break; 02010 02011 case OBM_TRUETYPE: { 02012 02013 PVOID p; 02014 HANDLE h; 02015 int nOffset; 02016 02017 /* 02018 * Offset into resource. 02019 */ 02020 if (gpsi->dmLogPixels == 120) { 02021 nOffset = OFFSET_120_DPI; 02022 } else { 02023 nOffset = OFFSET_96_DPI; 02024 } 02025 02026 lpName = (LPWSTR)(MAX_RESOURCE_INDEX - 02027 ((ULONG_PTR)lpName) + nOffset); 02028 02029 if (h = FINDRESOURCEW(hmod, (LPWSTR)lpName, RT_BITMAP)) { 02030 02031 if (h = LOADRESOURCE(hmod, h)) { 02032 02033 if (p = LOCKRESOURCE(h, hmod)) { 02034 02035 02036 hbmp = (HBITMAP)ObjectFromDIBResource(hmod, 02037 lpName, 02038 RT_BITMAP, 02039 cxDesired, 02040 cyDesired, 02041 flags); 02042 02043 UNLOCKRESOURCE(h, hmod); 02044 } 02045 02046 FREERESOURCE(h, hmod); 02047 } 02048 } 02049 02050 goto LoadBmpDone; 02051 } 02052 break; 02053 02054 default: 02055 fCombo = (wID == OBM_COMBO); 02056 fCheckBoxes = (wID == OBM_CHECKBOXES); 02057 02058 /* 02059 * hard loop to check for mapping. 02060 */ 02061 for (i=0; (i < MAX_BMPMAP) && (MapOemBmp[i].idDisp != wID); i++); 02062 02063 if (i == MAX_BMPMAP) 02064 goto LoadForReal; 02065 02066 if ((MapOemBmp[i].bFlags & MR_FAILFOR40) && 02067 (GETAPPVER() >= VER40)) { 02068 02069 FailOldLoad: 02070 RIPMSG0(RIP_WARNING, "LoadBitmap: old IDs not allowed for 4.0 apps"); 02071 return NULL; 02072 } 02073 02074 if (MapOemBmp[i].bFlags & MR_MONOCHROME) 02075 fMono = TRUE; 02076 02077 bm = MapOemBmp[i].idUser; 02078 02079 if ((bm == OBI_REDUCE_MBAR) || (bm == OBI_RESTORE_MBAR)) 02080 fMenu = TRUE; 02081 02082 cxDesired = gpsi->oembmi[bm].cx; 02083 cyDesired = gpsi->oembmi[bm].cy; 02084 02085 if (fMenu) 02086 cyDesired += (2 * SYSMET(CYEDGE)); 02087 02088 if (fCheckBoxes) { 02089 cxDesired *= NUM_BUTTON_STATES; 02090 cyDesired *= NUM_BUTTON_TYPES; 02091 } else if (fCombo) { 02092 cxDesired -= (2 * SYSMET(CXEDGE)); 02093 cyDesired -= (2 * SYSMET(CYEDGE)); 02094 } 02095 break; 02096 } 02097 02098 /* 02099 * Creates DIB section or color compatible. 02100 */ 02101 if (fMono) { 02102 02103 /* 02104 * Create mono-bitmaps as DIBs on NT. On Win95 this is 02105 * called as: 02106 * 02107 * hbmp = CreateBitmap(cxDesired, cyDesired, 1, 1, NULL); 02108 * 02109 * However, due to color-matching differences, we need to 02110 * use dibs to get the nearest-color-matching. At the 02111 * end of this routine we will convert to a true-mono so that 02112 * foreground/background matching can be performed normally. 02113 */ 02114 hbmp = CreateScreenBitmap(cxDesired, cyDesired, 1, 1, NULL, &f1Bpp); 02115 02116 } else { 02117 02118 hbmp = CreateScreenBitmap(cxDesired, cyDesired, 0, 0, NULL, &f1Bpp); 02119 } 02120 02121 if (hbmp == NULL) 02122 goto LoadBmpDone; 02123 02124 RtlEnterCriticalSection(&gcsHdc); 02125 hOldBmp = SelectBitmap(ghdcBits2, hbmp); 02126 UserAssert(GetBkColor(ghdcBits2) == RGB(255,255,255)); 02127 UserAssert(GetTextColor(ghdcBits2) == RGB(0, 0, 0)); 02128 02129 rc.top = 0; 02130 rc.left = 0; 02131 rc.bottom = cyDesired; 02132 rc.right = cxDesired; 02133 02134 if (fMono) { 02135 PatBlt(ghdcBits2, 0, 0, cxDesired, cyDesired, WHITENESS); 02136 } else { 02137 FillRect(ghdcBits2, 02138 &rc, 02139 ((fMenu | fSysMenu) ? SYSHBR(MENU) : SYSHBR(WINDOW))); 02140 } 02141 02142 if (fSysMenu) { 02143 int x = SYSMET(CXEDGE); 02144 int i; 02145 02146 cxDesired /= 2; 02147 02148 for (i=0; i < 2; i++) { 02149 02150 DrawIconEx(ghdcBits2, 02151 x, 02152 SYSMET(CYEDGE), 02153 gpsi->hIconSmWindows, 02154 cxDesired - 2 * SYSMET(CXEDGE), 02155 SYSMET(CYMENUSIZE) - SYSMET(CYEDGE), 02156 0, 02157 NULL, 02158 DI_NORMAL); 02159 02160 x += cxDesired; 02161 } 02162 02163 } else if (fCombo) { 02164 02165 /* 02166 * Revisit when we start using TTF -- that'll take care of 02167 * this hack. 02168 */ 02169 rc.top = -SYSMET(CYEDGE); 02170 rc.bottom += SYSMET(CYEDGE); 02171 rc.left = -SYSMET(CXEDGE); 02172 rc.right += SYSMET(CXEDGE); 02173 02174 DrawFrameControl(ghdcBits2, 02175 &rc, 02176 DFC_SCROLL, 02177 DFCS_SCROLLDOWN); 02178 02179 } else if (fCheckBoxes) { 02180 02181 int wType; 02182 int wState; 02183 int x; 02184 DWORD clrTextSave; 02185 DWORD clrBkSave; 02186 int y = 0; 02187 02188 for (wType=0; wType < NUM_BUTTON_TYPES; wType++) { 02189 02190 x = 0; 02191 02192 cxDesired = gpsi->oembmi[bm].cx; 02193 cyDesired = gpsi->oembmi[bm].cy; 02194 02195 if (wType == 1) { 02196 02197 /* 02198 * BOGUS UGLINESS -- will be fixed once the Graphics dudes 02199 * get me the icon TTF -- I'll revisit this then and make 02200 * REAL 02201 */ 02202 clrTextSave = SetTextColor(ghdcBits2, RESCLR_BLACK); 02203 clrBkSave = SetBkColor (ghdcBits2, RESCLR_WHITE); 02204 02205 for (wState = 0; wState < NUM_BUTTON_STATES; wState++) { 02206 02207 NtUserBitBltSysBmp(ghdcBits2, 02208 x, 02209 y, 02210 cxDesired, 02211 cyDesired, 02212 gpsi->oembmi[OBI_RADIOMASK].x, 02213 gpsi->oembmi[OBI_RADIOMASK].y, 02214 SRCAND); 02215 02216 NtUserBitBltSysBmp(ghdcBits2, 02217 x, 02218 y, 02219 cxDesired, 02220 cyDesired, 02221 gpsi->oembmi[bm].x, 02222 gpsi->oembmi[bm].y, 02223 SRCINVERT); 02224 x += cxDesired; 02225 bm++; 02226 } 02227 02228 SetTextColor(ghdcBits2, clrTextSave); 02229 SetBkColor(ghdcBits2, clrBkSave); 02230 02231 } else { 02232 02233 for (wState=0; wState < NUM_BUTTON_STATES; wState++) { 02234 02235 BitBltSysBmp(ghdcBits2, x, y, bm); 02236 x += cxDesired; 02237 bm++; 02238 } 02239 02240 /* 02241 * Skip OBI_*_CDI. 02242 */ 02243 bm++; 02244 } 02245 02246 y += cyDesired; 02247 } 02248 02249 } else { 02250 02251 BitBltSysBmp(ghdcBits2, 0, fMenu ? SYSMET(CYEDGE) : 0, bm); 02252 } 02253 02254 SelectBitmap(ghdcBits2, hOldBmp); 02255 02256 /* 02257 * If the bitmap was created as a 1bpp, we need to convert to a 02258 * true mono-bitmap. GDI performs different color-matching depending 02259 * upon this case. 02260 */ 02261 if (f1Bpp && hbmp) 02262 hbmp = Convert1BppToMonoBitmap(ghdcBits2, hbmp); 02263 02264 RtlLeaveCriticalSection(&gcsHdc); 02265 02266 } else { 02267 02268 LoadForReal: 02269 02270 hbmp = (HBITMAP)ObjectFromDIBResource(hmod, 02271 lpName, 02272 RT_BITMAP, 02273 cxDesired, 02274 cyDesired, 02275 flags); 02276 } 02277 02278 LoadBmpDone: 02279 02280 return hbmp; 02281 } 02282 02283 /***************************************************************************\ 02284 * LoadBitmapA (API) 02285 * LoadBitmapW (API) 02286 * 02287 * Loads a bitmap from client. If hmod == NULL, loads a bitmap from the 02288 * system. 02289 * 02290 \***************************************************************************/ 02291 02292 HBITMAP WINAPI LoadBitmapA( 02293 HINSTANCE hmod, 02294 LPCSTR lpName) 02295 { 02296 LPWSTR lpUniName; 02297 HBITMAP hRet; 02298 02299 if (ID(lpName)) 02300 return LoadBmp(hmod, (LPCWSTR)lpName, 0, 0, 0); 02301 02302 if (!MBToWCS(lpName, -1, &lpUniName, -1, TRUE)) 02303 return NULL; 02304 02305 hRet = LoadBmp(hmod, lpUniName, 0, 0, 0); 02306 02307 UserLocalFree(lpUniName); 02308 02309 return hRet; 02310 } 02311 02312 HBITMAP WINAPI LoadBitmapW( 02313 HINSTANCE hmod, 02314 LPCWSTR lpName) 02315 { 02316 return LoadBmp(hmod, lpName, 0, 0, 0); 02317 } 02318 02319 /***************************************************************************\ 02320 * LoadCursorA (API) 02321 * LoadCursorW (API) 02322 * 02323 * Loads a cursor from client. If hmod == NULL, loads a cursor from the 02324 * system. 02325 * 02326 * 05-Apr-1991 ScottLu Rewrote to work with client server. 02327 \***************************************************************************/ 02328 02329 HCURSOR WINAPI LoadCursorA( 02330 HINSTANCE hmod, 02331 LPCSTR lpName) 02332 { 02333 HCURSOR hRet; 02334 LPWSTR lpUniName; 02335 02336 if (ID(lpName)) 02337 return LoadCursorW(hmod, (LPWSTR)lpName); 02338 02339 if (!MBToWCS(lpName, -1, &lpUniName, -1, TRUE)) 02340 return NULL; 02341 02342 hRet = LoadCursorW(hmod, lpUniName); 02343 02344 UserLocalFree(lpUniName); 02345 02346 return hRet; 02347 } 02348 02349 HCURSOR WINAPI LoadCursorW( 02350 HINSTANCE hmod, 02351 LPCWSTR lpName) 02352 { 02353 02354 return LoadIcoCur(hmod, 02355 lpName, 02356 RT_CURSOR, 02357 0, 02358 0, 02359 LR_DEFAULTSIZE | LR_SHARED); 02360 02361 } 02362 02363 /***************************************************************************\ 02364 * LoadIconA (API) 02365 * LoadIconW (API) 02366 * 02367 * Loads an icon from client. If hmod == NULL, loads an icon from the 02368 * system. 02369 * 02370 * 05-Apr-1991 ScottLu Rewrote to work with client server. 02371 \***************************************************************************/ 02372 02373 HICON WINAPI LoadIconA( 02374 HINSTANCE hmod, 02375 LPCSTR lpName) 02376 { 02377 HICON hRet; 02378 LPWSTR lpUniName; 02379 02380 if (ID(lpName)) 02381 return LoadIconW(hmod, (LPWSTR)lpName); 02382 02383 if (!MBToWCS(lpName, -1, &lpUniName, -1, TRUE)) 02384 return NULL; 02385 02386 hRet = LoadIconW(hmod, lpUniName); 02387 02388 UserLocalFree(lpUniName); 02389 02390 return hRet; 02391 } 02392 02393 HICON WINAPI LoadIconW( 02394 HINSTANCE hmod, 02395 LPCWSTR lpName) 02396 { 02397 return LoadIcoCur(hmod, 02398 lpName, 02399 RT_ICON, 02400 0, 02401 0, 02402 LR_DEFAULTSIZE | LR_SHARED); 02403 } 02404 02405 /***************************************************************************\ 02406 * LoadImageA (API) 02407 * LoadImageW (API) 02408 * 02409 * Loads a bitmap, icon or cursor resource from client. If hmod == NULL, 02410 * then it will load from system-resources. 02411 * 02412 \***************************************************************************/ 02413 02414 HANDLE WINAPI LoadImageA( 02415 HINSTANCE hmod, 02416 LPCSTR lpName, 02417 UINT type, 02418 int cxDesired, 02419 int cyDesired, 02420 UINT flags) 02421 { 02422 LPWSTR lpUniName; 02423 HANDLE hRet; 02424 02425 if (ID(lpName)) 02426 return LoadImageW(hmod, 02427 (LPCWSTR)lpName, 02428 type, 02429 cxDesired, 02430 cyDesired, 02431 flags); 02432 02433 if (!MBToWCS(lpName, -1, &lpUniName, -1, TRUE)) 02434 return NULL; 02435 02436 hRet = LoadImageW(hmod, lpUniName, type, cxDesired, cyDesired, flags); 02437 02438 UserLocalFree(lpUniName); 02439 02440 return hRet; 02441 } 02442 02443 HANDLE WINAPI LoadImageW( 02444 HINSTANCE hmod, 02445 LPCWSTR lpName, 02446 UINT IMAGE_code, 02447 int cxDesired, 02448 int cyDesired, 02449 UINT flags) 02450 { 02451 /* 02452 * If we specified LR_LOADFROMFILE, then we can tweak the 02453 * flags to turn off LR_SHARED. 02454 */ 02455 if (flags & LR_LOADFROMFILE) 02456 flags &= ~LR_SHARED; 02457 02458 switch (IMAGE_code) { 02459 case IMAGE_BITMAP: 02460 return (HANDLE)LoadBmp(hmod, lpName, cxDesired, cyDesired, flags); 02461 02462 case IMAGE_CURSOR: 02463 #if 0 //CHRISWIL : oemInfo.fColorCursors doesn't exist on NT. 02464 if (!oemInfo.fColorCursors) 02465 flags |= LR_MONOCHROME; 02466 #endif 02467 02468 case IMAGE_ICON: 02469 02470 /* 02471 * On WinNT 3.51, an app can successfully load a 02472 * USER icon without specifying LR_SHARED. We enable 02473 * these apps to succeed, but make 4.0 apps conform to 02474 * Windows95 behavior. 02475 */ 02476 02477 if (!hmod && GETEXPWINVER(NULL) < VER40) { 02478 flags |= LR_SHARED; 02479 } 02480 02481 return (HANDLE)LoadIcoCur(hmod, 02482 lpName, 02483 ((IMAGE_code == IMAGE_ICON) ? RT_ICON : RT_CURSOR), 02484 cxDesired, 02485 cyDesired, 02486 flags); 02487 02488 default: 02489 RIPMSG0(RIP_WARNING, "LoadImage: invalid IMAGE_code"); 02490 return NULL; 02491 } 02492 } 02493 02494 /***************************************************************************\ 02495 * GetIconIdEx 02496 * 02497 * This one accepts width, height, and other flags. Just not exported right 02498 * now. 02499 * 02500 \***************************************************************************/ 02501 02502 UINT GetIconIdEx( 02503 HINSTANCE hmod, 02504 HANDLE hrsd, 02505 LPCWSTR lpszType, 02506 DWORD cxDesired, 02507 DWORD cyDesired, 02508 UINT LR_flags) 02509 { 02510 int idIcon = 0; 02511 LPNEWHEADER lpnh; 02512 02513 if (lpnh = (LPNEWHEADER)LOCKRESOURCE(hrsd, hmod)) { 02514 02515 /* 02516 * Do a sanity check on this data structure. Otherwise we'll GP FAULT 02517 * when extracting an icon from a corrupted area. Fix for B#9290. 02518 * SANKAR, 08/13/91 02519 */ 02520 if ((lpnh->Reserved == 0) && 02521 ((lpnh->ResType == IMAGE_ICON) || (lpnh->ResType == IMAGE_CURSOR))) { 02522 02523 idIcon = LookupIconIdFromDirectoryEx((PBYTE)lpnh, 02524 (lpszType == RT_ICON), 02525 cxDesired, 02526 cyDesired, 02527 LR_flags); 02528 } 02529 02530 UNLOCKRESOURCE(hrsd, hmod); 02531 } 02532 02533 return idIcon; 02534 } 02535 02536 /***************************************************************************\ 02537 * LoadDib (Worker) 02538 * 02539 * This is the worker-routine for loading a resource and returning a handle 02540 * to the object as a dib. 02541 * 02542 \***************************************************************************/ 02543 02544 HANDLE LoadDIB( 02545 HINSTANCE hmod, 02546 LPCWSTR lpName, 02547 LPWSTR type, 02548 DWORD cxDesired, 02549 DWORD cyDesired, 02550 UINT LR_flags) 02551 { 02552 HANDLE hDir; 02553 UINT idIcon; 02554 LPWSTR lpszGroupType; 02555 HANDLE hRes = NULL; 02556 02557 switch (PTR_TO_ID(type)) { 02558 02559 case PTR_TO_ID(RT_ICON): 02560 case PTR_TO_ID(RT_CURSOR): 02561 02562 lpszGroupType = RT_GROUP_CURSOR + (type - RT_CURSOR); 02563 02564 /* 02565 * For WOW support, OIC_ICON and OIC_SIZE need to be supported. 02566 * Since these resources match other existing resources, we map 02567 * them here so we produce results that emulates 02568 * behavor as if we had the actual resources in USER. 02569 * 02570 * Note that obsolete mapping of lpName in LoadIcoCur prevents 02571 * win4.0 apps from getting here. 02572 */ 02573 if (hmod == hmodUser) { 02574 02575 switch ((ULONG_PTR)lpName) { 02576 case OCR_SIZE: 02577 lpName = (LPCWSTR)OCR_SIZEALL_DEFAULT; 02578 break; 02579 02580 case OCR_ICON: 02581 lpName = (LPCWSTR)OCR_ICON_DEFAULT; 02582 break; 02583 } 02584 } 02585 /* 02586 * The resource is actually a directory which contains multiple 02587 * individual image resources we must choose from. 02588 * Locate the directory 02589 */ 02590 if (hDir = SplFindResource(hmod, lpName, (LPCWSTR)lpszGroupType)) { 02591 02592 /* 02593 * Load the directory. 02594 */ 02595 if (hDir = LOADRESOURCE(hmod, hDir)) { 02596 02597 /* 02598 * Get the name of the best individual image. 02599 */ 02600 if (idIcon = GetIconIdEx(hmod, 02601 hDir, 02602 type, 02603 cxDesired, 02604 cyDesired, 02605 LR_flags)) { 02606 02607 /* 02608 * NOTE: Don't free the directory resource!!! - ChipA. 02609 * We can't call SplFindResource here, because idIcon 02610 * is internal to us and GetDriverResourceId() 02611 * doesn't know how to map it. 02612 */ 02613 hRes = FINDRESOURCEW(hmod, MAKEINTRESOURCE(idIcon), type); 02614 } 02615 02616 /* 02617 * BOGUS: 02618 * It would be very cool if we could loop through all the 02619 * items in the directory and free 'em too. Free the ones 02620 * except for the one we're about to load, that is. 02621 * 02622 * Free directory resources TWICE so they get really freed. 02623 */ 02624 SplFreeResource(hDir, hmod, LR_flags); 02625 } 02626 } else { 02627 /* 02628 * Failed to load a regular icon\cursor. 02629 * Try to load an animated icon/cursor with the same name 02630 */ 02631 hRes = SplFindResource(hmod, lpName, 02632 PTR_TO_ID(type) == PTR_TO_ID(RT_CURSOR) ? RT_ANICURSOR : RT_ANIICON); 02633 } 02634 break; 02635 02636 case PTR_TO_ID(RT_BITMAP): 02637 hRes = SplFindResource(hmod, lpName, RT_BITMAP); 02638 break; 02639 02640 default: 02641 RIPMSG0(RIP_WARNING, "LoadDIB: Invalid resource type"); 02642 break; 02643 } 02644 02645 if (hRes) 02646 hRes = LOADRESOURCE(hmod, hRes); 02647 02648 return hRes; 02649 } 02650 02651 /***************************************************************************\ 02652 * LoadIcoCur (Worker) 02653 * 02654 * 02655 \***************************************************************************/ 02656 02657 HICON LoadIcoCur( 02658 HINSTANCE hmod, 02659 LPCWSTR pszResName, 02660 LPWSTR type, 02661 DWORD cxDesired, 02662 DWORD cyDesired, 02663 UINT LR_flags) 02664 { 02665 HICON hico; 02666 LPWSTR pszModName; 02667 WCHAR achModName[MAX_PATH]; 02668 02669 ConnectIfNecessary(); 02670 02671 /* 02672 * Setup module name and handles for lookup. 02673 */ 02674 if (hmod == NULL) { 02675 02676 hmod = hmodUser; 02677 pszModName = szUSER32; 02678 02679 } else { 02680 02681 WowGetModuleFileName(hmod, 02682 achModName, 02683 sizeof(achModName) / sizeof(WCHAR)); 02684 02685 pszModName = achModName; 02686 } 02687 02688 if (LR_flags & LR_CREATEDIBSECTION) 02689 LR_flags = (LR_flags & ~LR_CREATEDIBSECTION) | LR_CREATEREALDIB; 02690 02691 /* 02692 * Setup defaults. 02693 */ 02694 if ((hmod == hmodUser) && !IS_PTR(pszResName)) { 02695 02696 int imapMax; 02697 LPMAPRES lpMapRes; 02698 02699 /* 02700 * Map some old OEM IDs for people. 02701 */ 02702 if (type == RT_ICON) { 02703 02704 static MAPRES MapOemOic[] = { 02705 {OCR_ICOCUR, OIC_WINLOGO, MR_FAILFOR40} 02706 }; 02707 02708 lpMapRes = MapOemOic; 02709 imapMax = 1; 02710 02711 } else { 02712 02713 static MAPRES MapOemOcr[] = { 02714 {OCR_ICON, OCR_ICON, MR_FAILFOR40}, 02715 {OCR_SIZE, OCR_SIZE, MR_FAILFOR40} 02716 }; 02717 02718 lpMapRes = MapOemOcr; 02719 imapMax = 2; 02720 } 02721 02722 while (--imapMax >= 0) { 02723 02724 if (lpMapRes->idDisp == PTR_TO_ID(pszResName)) { 02725 02726 if ((lpMapRes->bFlags & MR_FAILFOR40) && 02727 GETAPPVER() >= VER40) { 02728 02729 RIPMSG1(RIP_WARNING, 02730 "LoadIcoCur: Old ID 0x%x not allowed for 4.0 apps", 02731 PTR_TO_ID(pszResName)); 02732 02733 return NULL; 02734 } 02735 02736 pszResName = MAKEINTRESOURCE(lpMapRes->idUser); 02737 break; 02738 } 02739 02740 ++lpMapRes; 02741 } 02742 } 02743 02744 /* 02745 * Determine size of requested object. 02746 */ 02747 cxDesired = GetIcoCurWidth(cxDesired , (type == RT_ICON), LR_flags, 0); 02748 cyDesired = GetIcoCurHeight(cyDesired, (type == RT_ICON), LR_flags, 0); 02749 02750 /* 02751 * See if this is a cached icon/cursor, and grab it if we have one 02752 * already. 02753 */ 02754 if (LR_flags & LR_SHARED) { 02755 02756 CURSORFIND cfSearch; 02757 02758 /* 02759 * Note that win95 fails to load any USER resources unless 02760 * LR_SHARED is specified - so we do too. Also, win95 will 02761 * ignore your cx, cy and LR_flag parameters and just give 02762 * you whats in the cache so we do too. 02763 * A shame but thats life... 02764 * 02765 * Setup search criteria. Since this is a load, we will have 02766 * no source-cursor to lookup. Find something respectable. 02767 */ 02768 cfSearch.hcur = (HCURSOR)NULL; 02769 cfSearch.rt = PtrToUlong(type); 02770 02771 if (hmod == hmodUser) { 02772 02773 cfSearch.cx = 0; 02774 cfSearch.cy = 0; 02775 cfSearch.bpp = 0; 02776 02777 } else { 02778 02779 cfSearch.cx = cxDesired; 02780 cfSearch.cy = cyDesired; 02781 02782 /* 02783 * On NT we have a more strict cache-lookup. By passing in (zero), we 02784 * will tell the cache-lookup to ignore the bpp. This fixes a problem 02785 * in Crayola Art Studio where the coloring-book cursor was being created 02786 * as an invisible cursor. This lookup is compatible with Win95. 02787 */ 02788 #if 0 02789 cfSearch.bpp = GetIcoCurBpp(LR_flags); 02790 #else 02791 cfSearch.bpp = 0; 02792 #endif 02793 } 02794 02795 hico = FindExistingCursorIcon(pszModName, pszResName, &cfSearch); 02796 02797 if (hico != NULL) 02798 goto IcoCurFound; 02799 } 02800 02801 #ifdef LATER // SanfordS 02802 /* 02803 * We need to handle the case where a configurable icon has been 02804 * loaded from some arbitrary module or file and someone now wants 02805 * to load the same thing in a different size or color content. 02806 * 02807 * A cheezier alternative is to just call CopyImage on what we 02808 * found. 02809 */ 02810 if (hmod == hmodUser) { 02811 hico = FindExistingCursorIcon(NULL, 02812 szUSER, 02813 type, 02814 pszResName, 02815 0, 02816 0, 02817 0); 02818 if (hico != NULL) { 02819 /* 02820 * Find out where the original came from and load it. 02821 * This may require some redesign to remember the 02822 * filename that LR_LOADFROMFILE images came from. 02823 */ 02824 _GetIconInfo(....); 02825 return LoadIcoCur(....); 02826 } 02827 } 02828 #endif 02829 02830 hico = (HICON)ObjectFromDIBResource(hmod, 02831 pszResName, 02832 type, 02833 cxDesired, 02834 cyDesired, 02835 LR_flags); 02836 02837 IcoCurFound: 02838 02839 return hico; 02840 } 02841 02842 /***************************************************************************\ 02843 * ObjectFromDIBResource 02844 * 02845 * 02846 \***************************************************************************/ 02847 HANDLE ObjectFromDIBResource( 02848 HINSTANCE hmod, 02849 LPCWSTR lpName, 02850 LPWSTR type, 02851 DWORD cxDesired, 02852 DWORD cyDesired, 02853 UINT LR_flags) 02854 { 02855 HANDLE hObj = NULL; 02856 02857 if (LR_flags & LR_LOADFROMFILE) { 02858 02859 hObj = RtlLoadObjectFromDIBFile(lpName, 02860 type, 02861 cxDesired, 02862 cyDesired, 02863 LR_flags); 02864 } else { 02865 02866 HANDLE hdib; 02867 02868 hdib = LoadDIB(hmod, lpName, type, cxDesired, cyDesired, LR_flags); 02869 02870 if (hdib != NULL) { 02871 02872 LPBITMAPINFOHEADER lpbih; 02873 02874 /* 02875 * We cast the resource-bits to a BITMAPINFOHEADER. If the 02876 * resource is a CURSOR type, then there are actually two 02877 * WORDs preceeding the BITMAPINFOHDEADER indicating the 02878 * hot-spot. Be careful in assuming you have a real 02879 * dib in this case. 02880 */ 02881 if(lpbih = (LPBITMAPINFOHEADER)LOCKRESOURCE(hdib, hmod)) { 02882 02883 switch (PTR_TO_ID(type)) { 02884 case PTR_TO_ID(RT_BITMAP): 02885 /* 02886 * Create a physical bitmap from the DIB. 02887 */ 02888 hObj = ConvertDIBBitmap(lpbih, 02889 cxDesired, 02890 cyDesired, 02891 LR_flags, 02892 NULL, 02893 NULL); 02894 break; 02895 02896 case PTR_TO_ID(RT_ICON): 02897 case PTR_TO_ID(RT_CURSOR): 02898 case PTR_TO_ID(RT_ANICURSOR): 02899 case PTR_TO_ID(RT_ANIICON): 02900 /* 02901 * Animated icon\cursors resources use the RIFF format 02902 */ 02903 if (ISRIFFFORMAT(lpbih)) { 02904 hObj = LoadCursorIconFromResource ((PBYTE)lpbih, lpName, cxDesired, cyDesired, LR_flags); 02905 } else { 02906 /* 02907 * Create the object from the DIB. 02908 */ 02909 hObj = ConvertDIBIcon(lpbih, 02910 hmod, 02911 lpName, 02912 (type == RT_ICON), 02913 cxDesired, 02914 cyDesired, 02915 LR_flags); 02916 } 02917 break; 02918 } 02919 02920 UNLOCKRESOURCE(hdib, hmod); 02921 } 02922 02923 /* 02924 * DO THIS TWICE! The resource compiler always makes icon images 02925 * (RT_ICON) in a group icon discardable, whether the group dude 02926 * is or not! So the first free won't really free the thing; 02927 * it'll just set the ref count to 0 and let the discard logic 02928 * go on its merry way. 02929 * 02930 * We take care of shared guys, so we don't need this dib no more. 02931 * Don't need this DIB no more no more, no more no more no more 02932 * don't need this DIB no more. 02933 */ 02934 SplFreeResource(hdib, hmod, LR_flags); 02935 } 02936 } 02937 02938 return hObj; 02939 } 02940 02941 /***************************************************************************\ 02942 * BitmapFromDIB 02943 * 02944 * Creates a bitmap-handle from a DIB-Spec. This function supports the 02945 * LR_CREATEDIBSECTION flag, sets proper color depth, and stretches the 02946 * DIBs as requested. 02947 * 02948 \***************************************************************************/ 02949 02950 HBITMAP BitmapFromDIB( 02951 int cxNew, 02952 int cyNew, 02953 WORD bPlanesNew, 02954 WORD bBitsPixelNew, 02955 UINT LR_flags, 02956 int cxOld, 02957 int cyOld, 02958 LPSTR lpBits, 02959 LPBITMAPINFO lpbi, 02960 HPALETTE hpal) 02961 { 02962 HBITMAP hbmpNew = NULL; 02963 BOOL fStretch; 02964 BOOL f1Bpp = FALSE; 02965 02966 RtlEnterCriticalSection(&gcsHdc); 02967 02968 if (cxNew == 0) 02969 cxNew = cxOld; 02970 02971 if (cyNew == 0) 02972 cyNew = cyOld; 02973 02974 fStretch = ((cxNew != cxOld) || (cyNew != cyOld)); 02975 02976 /* 02977 * If LR_flags indicate DIB-Section, then return that as the 02978 * bitmap handle. 02979 */ 02980 if (LR_flags & (LR_CREATEDIBSECTION | LR_CREATEREALDIB)) { 02981 02982 int cxTemp; 02983 int cyTemp; 02984 BOOL fOldFormat; 02985 LPVOID dwDummy; 02986 DWORD dwTemp; 02987 02988 #define lpbch ((LPBITMAPCOREHEADER)lpbi) 02989 02990 fOldFormat = ((WORD)lpbi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)); 02991 02992 if (fOldFormat) { 02993 02994 cxTemp = lpbch->bcWidth; 02995 cyTemp = lpbch->bcHeight; 02996 02997 lpbch->bcWidth = (WORD)cxNew; 02998 lpbch->bcHeight = (WORD)cyNew; 02999 03000 } else { 03001 03002 cxTemp = lpbi->bmiHeader.biWidth; 03003 cyTemp = lpbi->bmiHeader.biHeight; 03004 dwTemp = lpbi->bmiHeader.biCompression; 03005 03006 lpbi->bmiHeader.biWidth = cxNew; 03007 lpbi->bmiHeader.biHeight = cyNew; 03008 03009 if (dwTemp != BI_BITFIELDS) 03010 lpbi->bmiHeader.biCompression = BI_RGB; 03011 } 03012 03013 if (LR_flags & LR_CREATEREALDIB) { 03014 hbmpNew = CreateDIBitmap(ghdcBits2, 03015 (LPBITMAPINFOHEADER)lpbi, 03016 CBM_CREATEDIB, 03017 NULL, 03018 lpbi, 03019 DIB_RGB_COLORS); 03020 } else { 03021 hbmpNew = CreateDIBSection(ghdcBits2, 03022 lpbi, 03023 DIB_RGB_COLORS, 03024 &dwDummy, 03025 0, 03026 0); 03027 } 03028 03029 if (fOldFormat) { 03030 lpbch->bcWidth = (WORD)cxTemp; 03031 lpbch->bcHeight = (WORD)cyTemp; 03032 } else { 03033 lpbi->bmiHeader.biWidth = cxTemp; 03034 lpbi->bmiHeader.biHeight = cyTemp; 03035 lpbi->bmiHeader.biCompression = dwTemp; 03036 } 03037 #undef lpbch 03038 } 03039 03040 if (hbmpNew == NULL) { 03041 03042 hbmpNew = CreateScreenBitmap(cxNew, 03043 cyNew, 03044 bPlanesNew, 03045 bBitsPixelNew, 03046 NULL, 03047 &f1Bpp); 03048 } 03049 03050 if (hbmpNew) { 03051 03052 int nStretchMode; 03053 DWORD rgbBk; 03054 DWORD rgbText; 03055 HBITMAP hbmpT; 03056 BOOL fFail; 03057 03058 /* 03059 * We need to select in appropriate bitmap immediately! That way, 03060 * if we need to handle palette realization, the color matching 03061 * will work properly. 03062 */ 03063 hbmpT = SelectBitmap(ghdcBits2, hbmpNew); 03064 03065 /* 03066 * Setup for stretching 03067 */ 03068 if (fStretch) { 03069 nStretchMode = SetBestStretchMode(ghdcBits2, 03070 bPlanesNew, 03071 bBitsPixelNew); 03072 } 03073 03074 rgbBk = SetBkColor(ghdcBits2, RESCLR_WHITE); 03075 rgbText = SetTextColor(ghdcBits2, RESCLR_BLACK); 03076 03077 /* 03078 * Realize the palette. 03079 */ 03080 if (hpal) { 03081 #if DBG 03082 UserAssert(TEST_PUSIF(PUSIF_PALETTEDISPLAY)); 03083 #endif // DBG 03084 03085 hpal = SelectPalette(ghdcBits2, hpal, FALSE); 03086 RealizePalette(ghdcBits2); 03087 } 03088 03089 if (fStretch) { 03090 03091 fFail = SmartStretchDIBits(ghdcBits2, 03092 0, 03093 0, 03094 cxNew, 03095 cyNew, 03096 0, 03097 0, 03098 cxOld, 03099 cyOld, 03100 lpBits, 03101 lpbi, 03102 DIB_RGB_COLORS, 03103 SRCCOPY) <= 0; 03104 } else { 03105 03106 fFail = SetDIBits(ghdcBits2, 03107 hbmpNew, 03108 0, 03109 cyNew, 03110 lpBits, 03111 lpbi, 03112 DIB_RGB_COLORS) <= 0; 03113 } 03114 03115 /* 03116 * Unrealize the palette 03117 */ 03118 if (hpal) { 03119 SelectPalette(ghdcBits2, hpal, TRUE); 03120 RealizePalette(ghdcBits2); 03121 } 03122 03123 /* 03124 * Cleanup after stretching 03125 */ 03126 SetTextColor(ghdcBits2, rgbText); 03127 SetBkColor(ghdcBits2, rgbBk); 03128 if (fStretch) 03129 SetStretchBltMode(ghdcBits2, nStretchMode); 03130 03131 SelectBitmap(ghdcBits2, hbmpT); 03132 03133 /* 03134 * If the SetDIBits() of StretchDIBits() failed, it is probably because 03135 * GDI or the driver did not like the DIB format. This may happen if 03136 * the file is truncated and we are using a memory mapped file to read 03137 * the DIB in. In this case, an exception gets thrown in GDI, that it 03138 * traps and will return failure from the GDI call. 03139 */ 03140 03141 if (fFail) { 03142 DeleteObject(hbmpNew); 03143 hbmpNew = NULL; 03144 } 03145 } 03146 03147 /* 03148 * If the bitmap was created as a 1bpp, we need to convert to a 03149 * true mono-bitmap. GDI performs different color-matching depending 03150 * upon this case. 03151 */ 03152 if (f1Bpp && hbmpNew) 03153 hbmpNew = Convert1BppToMonoBitmap(ghdcBits2, hbmpNew); 03154 03155 RtlLeaveCriticalSection(&gcsHdc); 03156 return hbmpNew; 03157 } 03158 03159 /***************************************************************************\ 03160 * HowManyColors 03161 * 03162 * 03163 \***************************************************************************/ 03164 03165 DWORD HowManyColors( 03166 IN UPBITMAPINFOHEADER upbih, 03167 IN BOOL fOldFormat, 03168 OUT OPTIONAL LPBYTE *ppColorTable) 03169 { 03170 #define upbch ((UPBITMAPCOREHEADER)upbih) 03171 03172 if (fOldFormat) { 03173 if (ppColorTable != NULL) { 03174 *ppColorTable = (LPBYTE)(upbch + 1); 03175 } 03176 if (upbch->bcBitCount <= 8) 03177 return (1 << upbch->bcBitCount); 03178 } else { 03179 if (ppColorTable != NULL) { 03180 *ppColorTable = (LPBYTE)(upbih + 1); 03181 } 03182 if (upbih->biClrUsed) 03183 return (DWORD)upbih->biClrUsed; 03184 else if (upbih->biBitCount <= 8) 03185 return (1 << upbih->biBitCount); 03186 else if ((upbih->biBitCount == 16) || (upbih->biBitCount == 32)) 03187 return 3; 03188 } 03189 return 0; 03190 03191 #undef upbch 03192 } 03193 03194 /***************************************************************************\ 03195 * ChangeDibColors 03196 * 03197 * Given a DIB, processes LR_MONOCHROME, LR_LOADTRANSPARENT and 03198 * LR_LOADMAP3DCOLORS flags on the given header and colortable. 03199 * 03200 * 03201 \***************************************************************************/ 03202 03203 VOID ChangeDibColors( 03204 IN LPBITMAPINFOHEADER lpbih, 03205 IN UINT LR_flags) 03206 { 03207 LPDWORD lpColorTable; 03208 DWORD rgb; 03209 UINT iColor; 03210 UINT cColors; 03211 03212 cColors = HowManyColors(lpbih, FALSE, &(LPBYTE)lpColorTable); 03213 03214 /* 03215 * NT Bug 366661: Don't check the color count here b/c we will do different 03216 * things depending on what type of change we are performing. For example, 03217 * when loading hi-color/true-color icons, we always need to do the 03218 * monochrome conversion in order to properly get an icon-mask. 03219 */ 03220 03221 /* 03222 * LR_MONOCHROME is the only option that handles PM dibs. 03223 */ 03224 if (LR_flags & LR_MONOCHROME) { 03225 /* 03226 * LR_MONOCHROME is the only option that handles PM dibs. 03227 * 03228 * DO THIS NO MATTER WHETHER WE HAVE A COLOR TABLE! We need 03229 * to do this for mono conversion and for > 8 BPP 03230 * icons/cursors. In CopyDibHdr, we already made a copy of 03231 * the header big enough to hold 2 colors even on 16 and 24 03232 * BPP images. 03233 */ 03234 03235 lpbih->biBitCount = lpbih->biPlanes = 1; 03236 lpColorTable[0] = RESCLR_BLACK; 03237 lpColorTable[1] = RESCLR_WHITE; 03238 } else if (LR_flags & LR_LOADTRANSPARENT) { 03239 03240 LPBYTE pb; 03241 03242 /* 03243 * No color table! Do nothing. 03244 */ 03245 if (cColors == 0) { 03246 RIPMSG0(RIP_WARNING, "ChangeDibColors: DIB doesn't have a color table"); 03247 return; 03248 } 03249 03250 pb = (LPBYTE)(lpColorTable + cColors); 03251 03252 /* 03253 * Change the first pixel's color table entry to RGB_WINDOW 03254 * Gosh, I love small-endian 03255 */ 03256 if (lpbih->biCompression == 0) 03257 iColor = (UINT)pb[0]; 03258 else 03259 /* 03260 * RLE bitmap, will start with cnt,clr or 0,cnt,clr 03261 */ 03262 iColor = (UINT)(pb[0] == 0 ? pb[2] : pb[1]); 03263 03264 switch (cColors) { 03265 case BPP01_MAXCOLORS: 03266 iColor &= 0x01; 03267 break; 03268 03269 case BPP04_MAXCOLORS: 03270 iColor &= 0x0F; 03271 break; 03272 03273 case BPP08_MAXCOLORS: 03274 iColor &= 0xFF; 03275 break; 03276 } 03277 03278 rgb = (LR_flags & LR_LOADMAP3DCOLORS ? SYSRGB(3DFACE) : SYSRGB(WINDOW)); 03279 03280 lpColorTable[iColor] = RGBX(rgb); 03281 03282 } else if (LR_flags & LR_LOADMAP3DCOLORS) { 03283 03284 /* 03285 * Fix up the color table, mapping shades of grey to the current 03286 * 3D colors. 03287 */ 03288 for (iColor = 0; iColor < cColors; iColor++) { 03289 03290 switch (*lpColorTable & 0x00FFFFFF) { 03291 03292 case RGBX(RGB(223, 223, 223)): 03293 rgb = SYSRGB(3DLIGHT); 03294 goto ChangeColor; 03295 03296 case RGBX(RGB(192, 192, 192)): 03297 rgb = SYSRGB(3DFACE); 03298 goto ChangeColor; 03299 03300 case RGBX(RGB(128, 128, 128)): 03301 rgb = SYSRGB(3DSHADOW); 03302 03303 /* 03304 * NOTE: byte-order is different in DIBs than in RGBs 03305 */ 03306 ChangeColor: 03307 *lpColorTable = RGBX(rgb); 03308 break; 03309 } 03310 lpColorTable++; 03311 } 03312 } 03313 } 03314 03315 /***************************************************************************\ 03316 * ConvertDIBIcon 03317 * 03318 * Called when a cursor/icon in DIB format is loaded. This converts the 03319 * cursor/icon into the old format and returns the resource handle. IE, 03320 * grabs the DIB bits and transforms them into physical bitmap bits. 03321 * 03322 * 03323 * DIB Formats for icons/cursors 101 03324 * 03325 * Old Win 3.0 format icons/cursors start with an OLDICON/OLDCURSOR header 03326 * followed by a double high monochrome DIB. The height refered to in the 03327 * header is the icon/cursor height, not the DIB height which is twice as 03328 * high. The XOR mask is in the first-half of the DIB bits. 03329 * 03330 * Old PM format icons/cursors start with a BITMAPCOREHEADER and 03331 * are identical to the current win 3.1/NT format thereafter. 03332 * 03333 * Current NT/Chicago/Win 3.1 format icons/cursors start with 03334 * a BITAMPINFOHEADER. The height of this header refers to the height 03335 * of the first bitmap which may either be color or truely monochrome. 03336 * If its color, it is followed by the monochrome AND mask bits imediately 03337 * after the color bits. If it is truely monochrome, the AND and XOR 03338 * masks are totally contained in the first DIB bits and no more bits 03339 * follow. 03340 * 03341 * 5-Oct-1994 SanfordS Recreated 03342 \***************************************************************************/ 03343 03344 HICON ConvertDIBIcon( 03345 LPBITMAPINFOHEADER lpbih, 03346 HINSTANCE hmod, 03347 LPCWSTR lpName, 03348 BOOL fIcon, 03349 DWORD cxNew, 03350 DWORD cyNew, 03351 UINT LR_flags) 03352 { 03353 LPBITMAPINFOHEADER lpbihNew = NULL; 03354 LPSTR lpBitsNextMask = NULL; 03355 HICON hicoNew = NULL; 03356 BOOL fOldFormat = FALSE; 03357 CURSORDATA cur; 03358 WCHAR achModName[MAX_PATH]; 03359 03360 /* 03361 * Because Icons/Cursors always get public bitmaps, we cannot use 03362 * LR_CREATEDIBSECTION on them. 03363 */ 03364 if (LR_flags & LR_CREATEDIBSECTION) 03365 LR_flags = (LR_flags & ~LR_CREATEDIBSECTION) | LR_CREATEREALDIB; 03366 03367 RtlZeroMemory(&cur, sizeof(cur)); 03368 03369 if (!fIcon) { 03370 /* 03371 * Cursors have an extra two words preceeding the BITMAPINFOHEADER 03372 * indicating the hot-spot. After doing the increments, the 03373 * pointer should be at the dib-header. 03374 */ 03375 cur.xHotspot = (short)(int)*(((LPWORD)lpbih)++); 03376 cur.yHotspot = (short)(int)*(((LPWORD)lpbih)++); 03377 } 03378 03379 /* 03380 * Get the XOR/Color mask. 03381 * The XOR bits are first in the DIB because the header info 03382 * pertains to them. 03383 * The AND mask is always monochrome. 03384 */ 03385 lpBitsNextMask = NULL; // not passing lpBits in. 03386 cur.hbmColor = ConvertDIBBitmap(lpbih, 03387 cxNew, 03388 cyNew, 03389 LR_flags, 03390 &lpbihNew, 03391 &lpBitsNextMask); 03392 if (cur.hbmColor == NULL) 03393 return NULL; 03394 03395 if (hmod == NULL) { 03396 cur.lpModName = NULL; 03397 } else { 03398 cur.CURSORF_flags = CURSORF_FROMRESOURCE; 03399 if (hmod == hmodUser) { 03400 cur.lpModName = szUSER32; 03401 } else { 03402 WowGetModuleFileName(hmod, 03403 achModName, 03404 sizeof(achModName) / sizeof(WCHAR)); 03405 cur.lpModName = achModName; 03406 } 03407 } 03408 cur.rt = (fIcon ? PTR_TO_ID(RT_ICON) : PTR_TO_ID(RT_CURSOR)); 03409 cur.lpName = (LPWSTR)lpName; 03410 cur.bpp = lpbihNew->biBitCount * lpbihNew->biPlanes; 03411 03412 if (cxNew == 0) 03413 cxNew = lpbihNew->biWidth; 03414 03415 if (cyNew == 0) 03416 cyNew = lpbihNew->biHeight / 2; 03417 03418 if (!fIcon) { 03419 03420 cur.xHotspot = MultDiv(cur.xHotspot, 03421 cxNew, 03422 lpbihNew->biWidth); 03423 cur.yHotspot = MultDiv(cur.yHotspot, 03424 cyNew, 03425 lpbihNew->biHeight / 2); 03426 } else { 03427 03428 /* 03429 * For an icon the hot spot is the center of the icon 03430 */ 03431 cur.xHotspot = (INT)(cxNew) / 2; 03432 cur.yHotspot = (INT)(cyNew) / 2; 03433 } 03434 03435 /* 03436 * Setup header for monochrome DIB. Note that we use the COPY. 03437 */ 03438 ChangeDibColors(lpbihNew, LR_MONOCHROME); 03439 03440 if (lpBitsNextMask != NULL) { 03441 cur.hbmMask = BitmapFromDIB(cxNew, 03442 cyNew * 2, 03443 1, 03444 1, 03445 0, 03446 lpbihNew->biWidth, 03447 lpbihNew->biHeight, 03448 lpBitsNextMask, 03449 (LPBITMAPINFO)lpbihNew, 03450 NULL); 03451 if (cur.hbmMask == NULL) { 03452 DeleteObject(cur.hbmColor); 03453 UserLocalFree(lpbihNew); 03454 return NULL; 03455 } 03456 03457 } else { 03458 cur.hbmMask = cur.hbmColor; 03459 cur.hbmColor = NULL; 03460 } 03461 03462 cur.cx = cxNew; 03463 cur.cy = cyNew * 2; 03464 03465 /* 03466 * Free our dib header copy allocated by ConvertDIBBitmap 03467 */ 03468 UserLocalFree(lpbihNew); 03469 03470 if (LR_flags & LR_SHARED) 03471 cur.CURSORF_flags |= CURSORF_LRSHARED; 03472 03473 if (LR_flags & LR_GLOBAL) 03474 cur.CURSORF_flags |= CURSORF_GLOBAL; 03475 03476 if (LR_flags & LR_ACONFRAME) 03477 cur.CURSORF_flags |= CURSORF_ACONFRAME; 03478 03479 return CreateIcoCur(&cur); 03480 } 03481 03482 /***************************************************************************\ 03483 * TrulyMonochrome 03484 * 03485 * Checks to see if a DIB colro table is truly monochrome. ie: the color 03486 * table has black & white entries only. 03487 * 03488 \***************************************************************************/ 03489 03490 BOOL TrulyMonochrome( 03491 LPVOID lpColorTable, 03492 BOOL fOldFormat) 03493 { 03494 #define lpRGB ((UNALIGNED LONG *)lpColorTable) 03495 #define lpRGBw ((UNALIGNED WORD *)lpColorTable) 03496 03497 if (fOldFormat) { 03498 03499 /* 03500 * Honey - its triplets. 03501 */ 03502 if (lpRGBw[0] == 0x0000) 03503 return (lpRGBw[1] == 0xFF00) && (lpRGBw[2] == 0xFFFF); 03504 else if (lpRGBw[0] == 0xFFFF) 03505 return (lpRGBw[1] == 0x00FF) && (lpRGBw[2] == 0x0000); 03506 03507 } else { 03508 03509 /* 03510 * Honey - its quadruplets! 03511 */ 03512 if (lpRGB[0] == RESCLR_BLACK) 03513 return (lpRGB[1] == RESCLR_WHITE); 03514 else if (lpRGB[0] == RESCLR_WHITE) 03515 return (lpRGB[1] == RESCLR_BLACK); 03516 } 03517 03518 #undef lpRGB 03519 #undef lpRGBw 03520 03521 return FALSE; 03522 } 03523 03524 /***************************************************************************\ 03525 * CopyDibHdr 03526 * 03527 * Copies and converts a DIB resource header 03528 * 03529 * Handles conversion of OLDICON, OLDCURSOR and BITMAPCOREHEADER 03530 * structures to BITMAPINFOHEADER headers. 03531 * 03532 * Note: fSingleHeightMasks is set for OLDICON and OLDCURSOR formats. 03533 * This identifies that a monochrome AND/Color mask 03534 * is NOT double height as it is in the newer formats. 03535 * 03536 * NOTE: On the off chance that LR_LOADTRANSPARENT is used, we want to 03537 * copy a DWORD of the bits. Since DIB bits are DWORD aligned, we know 03538 * at least a DWORD is there, even if the thing is a 1x1 mono bmp. 03539 * 03540 * The returned buffer is allocated in this function and needs to be 03541 * freed by the caller. 03542 * 03543 * 22-Oct-1995 SanfordS Revised 03544 \***************************************************************************/ 03545 03546 LPBITMAPINFOHEADER CopyDibHdr( 03547 IN UPBITMAPINFOHEADER upbih, 03548 OUT LPSTR *lplpBits, 03549 OUT LPBOOL lpfMono) 03550 { 03551 03552 #define upbch ((UPBITMAPCOREHEADER)upbih) 03553 03554 DWORD cColors; 03555 DWORD i; 03556 LPBITMAPINFOHEADER lpbihNew; 03557 DWORD cbAlloc; 03558 LPBYTE lpColorTable; 03559 struct { 03560 BITMAPINFOHEADER bih; 03561 DWORD rgb[256]; 03562 DWORD dwBuffer; 03563 } Fake; 03564 03565 switch (upbih->biSize) { 03566 case sizeof(BITMAPINFOHEADER): 03567 /* 03568 * Cool. No conversion needed. 03569 */ 03570 cColors = HowManyColors(upbih, FALSE, &lpColorTable); 03571 *lplpBits = (LPSTR)(((LPDWORD)lpColorTable) + cColors); 03572 break; 03573 03574 case sizeof(BITMAPCOREHEADER): 03575 /* 03576 * Convert the BITMAPCOREHEADER to a BITMAPINFOHEADER 03577 */ 03578 Fake.bih.biSize = sizeof(BITMAPINFOHEADER); 03579 Fake.bih.biWidth = upbch->bcWidth; 03580 Fake.bih.biHeight = upbch->bcHeight; 03581 Fake.bih.biPlanes = upbch->bcPlanes; 03582 Fake.bih.biBitCount = upbch->bcBitCount; 03583 Fake.bih.biCompression = 03584 Fake.bih.biXPelsPerMeter = 03585 Fake.bih.biYPelsPerMeter = 03586 Fake.bih.biClrImportant = 0; 03587 Fake.bih.biClrUsed = cColors = 03588 HowManyColors(upbih, TRUE, &lpColorTable); 03589 Fake.bih.biSizeImage = 03590 BitmapWidth(Fake.bih.biWidth, Fake.bih.biBitCount) * 03591 Fake.bih.biHeight; 03592 /* 03593 * Copy and convert tripplet color table to rgbQuad color table. 03594 */ 03595 for (i = 0; i < cColors; i++, lpColorTable += 3) { 03596 03597 Fake.rgb[i] = lpColorTable[0] + 03598 (lpColorTable[1] << 8) + 03599 (lpColorTable[2] << 16); 03600 } 03601 03602 Fake.rgb[i] = *(DWORD UNALIGNED *)lpColorTable; // For LR_LOADTRANSPARENT 03603 upbih = (UPBITMAPINFOHEADER)&Fake; 03604 *lplpBits = lpColorTable; 03605 break; 03606 03607 default: 03608 03609 #define upOldIcoCur ((UPOLDCURSOR)upbih) 03610 03611 if (upOldIcoCur->bType == BMR_ICON || 03612 upOldIcoCur->bType == BMR_CURSOR) { 03613 /* 03614 * Convert OLDICON/OLDCURSOR header to BITMAPINFHEADER 03615 */ 03616 RIPMSG0(RIP_WARNING, "USER32:Converting a OLD header. - email sanfords if you see this"); 03617 Fake.bih.biSize = sizeof(BITMAPINFOHEADER); 03618 Fake.bih.biWidth = upOldIcoCur->cx; 03619 Fake.bih.biHeight = upOldIcoCur->cy * 2; 03620 Fake.bih.biPlanes = 03621 Fake.bih.biBitCount = 1; 03622 Fake.bih.biCompression = 03623 Fake.bih.biXPelsPerMeter = 03624 Fake.bih.biYPelsPerMeter = 03625 Fake.bih.biClrImportant = 0; 03626 Fake.bih.biClrUsed = cColors = BPP01_MAXCOLORS; 03627 Fake.bih.biSizeImage = 03628 BitmapWidth(upOldIcoCur->cx, 1) * upOldIcoCur->cy; 03629 Fake.rgb[0] = RESCLR_BLACK; 03630 Fake.rgb[1] = RESCLR_WHITE; 03631 upbih = (LPBITMAPINFOHEADER)&Fake; 03632 *lplpBits = upOldIcoCur->abBitmap; 03633 Fake.rgb[2] = *((LPDWORD)*lplpBits); // For LR_LOADTRANSPARENT 03634 03635 } else { 03636 03637 RIPMSG0(RIP_WARNING, "ConvertDIBBitmap: not a valid format"); 03638 return NULL; 03639 } 03640 03641 #undef pOldIcoCur 03642 03643 break; 03644 } 03645 03646 *lpfMono = (cColors == BPP01_MAXCOLORS) && 03647 TrulyMonochrome((LPBYTE)upbih + sizeof(BITMAPINFOHEADER), FALSE); 03648 03649 cbAlloc = sizeof(BITMAPINFOHEADER) + (cColors * sizeof(RGBQUAD)) + 4; 03650 03651 if (lpbihNew = UserLocalAlloc(0, cbAlloc)) 03652 RtlCopyMemory(lpbihNew, upbih, cbAlloc); 03653 03654 return lpbihNew; 03655 03656 #undef upbch 03657 03658 } 03659 03660 /***************************************************************************\ 03661 * ConvertDIBBitmap 03662 * 03663 * This takes a BITMAPCOREHEADER, OLDICON, OLDCURSOR or BITMAPINFOHEADER DIB 03664 * specification and creates a physical object from it. 03665 * Handles Color fixups, DIB sections, color depth, and stretching options. 03666 * 03667 * Passes back: (if lplpbih is not NULL) 03668 * lplpbih = copy of given header converted to BITMAPINFOHEADER form. 03669 * lplpBits = pointer to next mask bits, or NULL if no second mask. 03670 * Caller must free lplpbih returned. 03671 * 03672 * If lplpBits is not NULL and points to a non-NULL value, it supplies 03673 * the location of the DIB bits allowing the header to be from a different 03674 * location. 03675 * 03676 * 04-Oct-1995 SanfordS Recreated. 03677 \***************************************************************************/ 03678 03679 HBITMAP ConvertDIBBitmap( 03680 IN UPBITMAPINFOHEADER upbih, 03681 IN DWORD cxDesired, 03682 IN DWORD cyDesired, 03683 IN UINT LR_flags, 03684 OUT OPTIONAL LPBITMAPINFOHEADER *lplpbih, 03685 IN OUT OPTIONAL LPSTR *lplpBits) 03686 { 03687 LPBITMAPINFOHEADER lpbihNew; 03688 BOOL fMono, fMonoGiven; 03689 BYTE bPlanesDesired; 03690 BYTE bppDesired; 03691 LPSTR lpBits; 03692 HBITMAP hBmpRet; 03693 03694 /* 03695 * Make a copy of the DIB-Header. This returns a pointer 03696 * which was allocated, so it must be freed later. 03697 * The also converts the header to BITMAPINFOHEADER format. 03698 */ 03699 if ((lpbihNew = CopyDibHdr(upbih, &lpBits, &fMono)) == NULL) 03700 return NULL; 03701 03702 /* 03703 * When loading a DIB file, we may need to use a different 03704 * bits pointer. See RtlRes.c/RtlLoadObjectFromDIBFile. 03705 */ 03706 if (lplpBits && *lplpBits) 03707 lpBits = *lplpBits; 03708 03709 fMonoGiven = fMono; 03710 03711 if (!fMono) { 03712 03713 if (LR_flags & (LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS)) 03714 ChangeDibColors(lpbihNew, LR_flags & ~LR_MONOCHROME); 03715 03716 bPlanesDesired = gpsi->Planes; 03717 bppDesired = gpsi->BitsPixel; 03718 fMono = LR_flags & LR_MONOCHROME; 03719 } 03720 03721 if (fMono) { 03722 bPlanesDesired = 03723 bppDesired = 1; 03724 } 03725 03726 /* 03727 * HACK area 03728 */ 03729 if (lplpbih != NULL) { 03730 03731 /* 03732 * pass back the translated/copied header 03733 */ 03734 *lplpbih = lpbihNew; 03735 03736 /* 03737 * When loading icon/cursors on a system with multiple monitors 03738 * with different color depths, always convert to VGA color. 03739 */ 03740 if (!fMono && !SYSMET(SAMEDISPLAYFORMAT)) { 03741 bPlanesDesired = 1; 03742 bppDesired = 4; 03743 } 03744 03745 /* 03746 * Return a ponter to the bits following this set of bits 03747 * if there are any there. 03748 * 03749 * Note that the header given with an ICON DIB always reflects 03750 * twice the height of the icon desired but the COLOR bitmap 03751 * (if there is one) will only be half that high. We need to 03752 * fixup cyDesired for monochrome icons so that the mask isnt 03753 * stretched to half the height its supposed to be. Color 03754 * bitmaps, however, must have the header corrected to reflect 03755 * the bits actual height which is half what the header said. 03756 * The correction must later be backed out so that the returned 03757 * header reflects the dimensions of the XOR mask that immediately 03758 * follows the color mask. 03759 */ 03760 if (fMonoGiven) { 03761 03762 *lplpBits = NULL; 03763 03764 if (cyDesired) 03765 cyDesired <<= 1; // mono icon bitmaps are double high. 03766 03767 } else { 03768 03769 UserAssert(!(lpbihNew->biHeight & 1)); 03770 lpbihNew->biHeight >>= 1; // color icon headers are off by 2 03771 03772 /* 03773 * Gross calculation! We subtract the XOR part of the mask 03774 * for this calculation so that we submit a double-high mask. 03775 * The first half of this is garbage, but for icons its not 03776 * used. This may be a bug for cursor use of icons. 03777 */ 03778 *lplpBits = lpBits + 03779 (BitmapWidth(lpbihNew->biWidth, lpbihNew->biBitCount) - 03780 BitmapWidth(lpbihNew->biWidth, 1)) * 03781 lpbihNew->biHeight; 03782 } 03783 } 03784 03785 if (cxDesired == 0) 03786 cxDesired = lpbihNew->biWidth; 03787 03788 if (cyDesired == 0) 03789 cyDesired = lpbihNew->biHeight; 03790 03791 hBmpRet = BitmapFromDIB(cxDesired, 03792 cyDesired, 03793 bPlanesDesired, 03794 bppDesired, 03795 LR_flags, 03796 lpbihNew->biWidth, 03797 lpbihNew->biHeight, 03798 lpBits, 03799 (LPBITMAPINFO)lpbihNew, 03800 NULL); 03801 03802 if (lplpbih == NULL || hBmpRet == NULL) { 03803 UserLocalFree(lpbihNew); 03804 } else if (!fMonoGiven) { 03805 lpbihNew->biHeight <<= 1; // restore header for next mask 03806 } 03807 03808 return hBmpRet; 03809 } 03810 03811 /***************************************************************************\ 03812 * MyAbs 03813 * 03814 * Calcules my weighted absolute value of the difference between 2 nums. 03815 * This of course normalizes values to >= zero. But it also doubles them 03816 * if valueHave < valueWant. This is because you get worse results trying 03817 * to extrapolate from less info up then interpolating from more info down. 03818 * I paid $150 to take the SAT. I'm damned well going to get my vocab's 03819 * money worth. 03820 * 03821 \***************************************************************************/ 03822 03823 UINT MyAbs( 03824 int valueHave, 03825 int valueWant) 03826 { 03827 int diff = (valueHave - valueWant); 03828 03829 if (diff < 0) 03830 diff = 2 * (-diff); 03831 03832 return (UINT)diff; 03833 } 03834 03835 /***************************************************************************\ 03836 * Magnitude 03837 * 03838 * Used by the color-delta calculations. The reason is that num colors is 03839 * always a power of 2. So we use the log 2 of the want vs. have values 03840 * to avoid having weirdly huge sets. 03841 * 03842 \***************************************************************************/ 03843 03844 UINT Magnitude( 03845 int nValue) 03846 { 03847 if (nValue < 4) 03848 return 1; 03849 else if (nValue < 8) 03850 return 2; 03851 else if (nValue < 16) 03852 return 3; 03853 else if (nValue < 256) 03854 return 4; 03855 else 03856 return 8; 03857 } 03858 03859 /***************************************************************************\ 03860 * MatchImage 03861 * 03862 * This function takes LPINTs for width & height in case of "real size". 03863 * For this option, we use dimensions of 1st icon in resdir as size to 03864 * load, instead of system metrics. 03865 * 03866 * Returns a number that measures how "far away" the given image is 03867 * from a desired one. The value is 0 for an exact match. Note that our 03868 * formula has the following properties: 03869 * (1) Differences in width/height count much more than differences in 03870 * color format. 03871 * (2) Fewer colors give a smaller difference than more 03872 * (3) Bigger images are better than smaller, since shrinking produces 03873 * better results than stretching. 03874 * 03875 * The formula is the sum of the following terms: 03876 * Log2(colors wanted) - Log2(colors really), times -2 if the image 03877 * has more colors than we'd like. This is because we will lose 03878 * information when converting to fewer colors, like 16 color to 03879 * monochrome. 03880 * Log2(width really) - Log2(width wanted), times -2 if the image is 03881 * narrower than what we'd like. This is because we will get a 03882 * better result when consolidating more information into a smaller 03883 * space, than when extrapolating from less information to more. 03884 * Log2(height really) - Log2(height wanted), times -2 if the image is 03885 * shorter than what we'd like. This is for the same reason as 03886 * the width. 03887 * 03888 * Let's step through an example. Suppose we want a 16 color, 32x32 image, 03889 * and are choosing from the following list: 03890 * 16 color, 64x64 image 03891 * 16 color, 16x16 image 03892 * 8 color, 32x32 image 03893 * 2 color, 32x32 image 03894 * 03895 * We'd prefer the images in the following order: 03896 * 8 color, 32x32 : Match value is 0 + 0 + 1 == 1 03897 * 16 color, 64x64 : Match value is 1 + 1 + 0 == 2 03898 * 2 color, 32x32 : Match value is 0 + 0 + 3 == 3 03899 * 16 color, 16x16 : Match value is 2*1 + 2*1 + 0 == 4 03900 * 03901 \***************************************************************************/ 03902 03903 UINT MatchImage( 03904 LPRESDIR lprd, 03905 LPINT lpcxWant, 03906 LPINT lpcyWant, 03907 UINT uColorsWant, 03908 BOOL fIcon) 03909 { 03910 UINT uColorsNew; 03911 int cxNew; 03912 int cyNew; 03913 03914 cxNew = lprd->Icon.Width; 03915 cyNew = lprd->Icon.Height; 03916 03917 if (fIcon) { 03918 uColorsNew = lprd->Icon.ColorCount; 03919 } else { 03920 cyNew >>= 1; 03921 uColorsNew = BPP01_MAXCOLORS; 03922 } 03923 03924 /* 03925 * 0 really means maximum size (256) or colors (256). 03926 */ 03927 if (!cxNew) 03928 cxNew = BPP08_MAXCOLORS; 03929 03930 if (!*lpcxWant) 03931 *lpcxWant = cxNew; 03932 03933 if (!cyNew) 03934 cyNew = BPP08_MAXCOLORS; 03935 03936 if (!*lpcyWant) 03937 *lpcyWant = cyNew; 03938 03939 if (!uColorsNew) 03940 uColorsNew = BPP08_MAXCOLORS; 03941 03942 /* 03943 * Here are the rules for our "match" formula: 03944 * (1) A close size match is much preferable to a color match 03945 * (2) Fewer colors are better than more 03946 * (3) Bigger icons are better than smaller 03947 * 03948 * The color count, width, and height are powers of 2. So we use Magnitude() 03949 * which calculates the order of magnitude in base 2. 03950 */ 03951 #if 0 //CHRISWIL: Not in Win95 03952 03953 return (MagnitudeDiff(uColorsWant, uColorsNew) + 03954 MagnitudeDiff(cxNew, *lpcxWant) + 03955 MagnitudeDiff(cyNew, *lpcyWant)); 03956 03957 #else 03958 03959 return( 2*MyAbs(Magnitude(uColorsWant), Magnitude(uColorsNew)) + 03960 MyAbs(cxNew, *lpcxWant) + 03961 MyAbs(cyNew, *lpcyWant)); 03962 #endif 03963 } 03964 03965 /***************************************************************************\ 03966 * GetBestImage 03967 * 03968 * Among the different forms of images, choose the one that best matches the 03969 * color format & dimensions of the request. We try to match the size, then 03970 * the color info. So we find the item that 03971 * 03972 * (1) Has closest dimensions (smaller or bigger equally good) to minimize 03973 * the width, height difference 03974 * (2) Has best colors. We favor less over more colors. 03975 * 03976 * If we find an identical match, we return immediately. 03977 * 03978 \***************************************************************************/ 03979 03980 UINT GetBestImage( 03981 LPRESDIR lprd, 03982 UINT uCount, 03983 int cxDesired, 03984 int cyDesired, 03985 UINT bpp, 03986 BOOL fIcon) 03987 { 03988 UINT uIndex; 03989 UINT uT; 03990 UINT uIndexBest = 0; 03991 UINT uBest = (UINT)-1; 03992 03993 03994 /* 03995 * Get desired number of colors in # value, not bits value. Note that 03996 * we do NOT allow you to have 16- or 32- or 24- bit color icons. 03997 * 03998 * the icon resources can be 16, 24, 32 bpp, but the restable only has 03999 * a color count, so a HiColor icon would have a max value in the 04000 * restable. we treat a 0 in the color count as "max colors" 04001 */ 04002 if (bpp == 0) 04003 bpp = (UINT)gpsi->BitCount; 04004 04005 if (bpp > 8) 04006 bpp = 8; 04007 04008 bpp = 1 << bpp; 04009 04010 /* 04011 * Loop through resource entries, saving the "closest" item so far. Most 04012 * of the real work is in MatchImage(), which uses a fabricated formula 04013 * to give us the results that we desire. Namely, an image as close in 04014 * size to what we want preferring bigger over smaller, then an image 04015 * with the right color format 04016 */ 04017 for (uIndex = 0; uIndex < uCount; uIndex++, lprd++) { 04018 04019 /* 04020 * Get "matching" value. How close are we to what we want? 04021 */ 04022 uT = MatchImage(lprd, &cxDesired, &cyDesired, bpp, fIcon); 04023 04024 if (!uT) { 04025 04026 /* 04027 * We've found an exact match! 04028 */ 04029 return uIndex; 04030 04031 } else if (uT < uBest) { 04032 04033 /* 04034 * We've found a better match than the current alternative. 04035 */ 04036 uBest = uT; 04037 uIndexBest = uIndex; 04038 } 04039 } 04040 04041 return uIndexBest; 04042 } 04043 04044 /***************************************************************************\ 04045 * GetIcoCurWidth 04046 * 04047 * When zero is passed in for a dimension, calculates what size we should 04048 * really used. Done in a couple o' places, so made it a FN(). 04049 * 04050 \***************************************************************************/ 04051 04052 _inline DWORD GetIcoCurWidth( 04053 DWORD cxOrg, 04054 BOOL fIcon, 04055 UINT lrFlags, 04056 DWORD cxDes) 04057 { 04058 if (cxOrg) { 04059 return cxOrg; 04060 } else if (lrFlags & LR_DEFAULTSIZE) { 04061 return (fIcon ? SYSMET(CXICON) : SYSMET(CXCURSOR)); 04062 } else { 04063 return cxDes; 04064 } 04065 } 04066 04067 /***************************************************************************\ 04068 * GetIcoCurHeight 04069 * 04070 * Vertical counterpart to GetWidth(). 04071 * 04072 \***************************************************************************/ 04073 04074 _inline DWORD GetIcoCurHeight( 04075 DWORD cyOrg, 04076 BOOL fIcon, 04077 UINT lrFlags, 04078 DWORD cyDes) 04079 { 04080 if (cyOrg) { 04081 return cyOrg; 04082 } else if (lrFlags & LR_DEFAULTSIZE) { 04083 return (fIcon ? SYSMET(CYICON) : SYSMET(CYCURSOR)); 04084 } else { 04085 return cyDes; 04086 } 04087 } 04088 04089 /***************************************************************************\ 04090 * GetIcoCurBpp 04091 * 04092 * Returns best match Bpp based on lr-flags. 04093 * 04094 \***************************************************************************/ 04095 04096 _inline DWORD GetIcoCurBpp( 04097 UINT lrFlags) 04098 { 04099 if (lrFlags & LR_MONOCHROME) { 04100 04101 #if DBG 04102 if (lrFlags & LR_VGACOLOR) { 04103 RIPMSG0(RIP_WARNING, "lrFlags has both MONOCHROME and VGACOLOR; assuming MONOCHROME"); 04104 } 04105 #endif 04106 return 1; 04107 04108 } else if ( 04109 TEST_PUSIF(PUSIF_PALETTEDISPLAY) || 04110 (lrFlags & LR_VGACOLOR) || 04111 !SYSMET(SAMEDISPLAYFORMAT)) { 04112 04113 return 4; 04114 } else { 04115 return 0; 04116 } 04117 } 04118 04119 /***************************************************************************\ 04120 * WOWFindResourceExWCover 04121 * 04122 * The WOW FindResource routines expect an ansi string so we have to 04123 * convert the calling string IFF it is not an ID 04124 * 04125 \***************************************************************************/ 04126 04127 HANDLE WOWFindResourceExWCover( 04128 HANDLE hmod, 04129 LPCWSTR rt, 04130 LPCWSTR lpUniName, 04131 WORD LangId) 04132 { 04133 LPSTR lpAnsiName; 04134 HANDLE hRes; 04135 04136 if (ID(lpUniName)) 04137 return FINDRESOURCEEXA(hmod, (LPSTR)lpUniName, (LPSTR)rt, LangId); 04138 04139 /* 04140 * Otherwise convert the name of the menu then call LoadMenu 04141 */ 04142 if (!WCSToMB(lpUniName, -1, &lpAnsiName, -1, TRUE)) 04143 return NULL; 04144 04145 hRes = FINDRESOURCEEXA(hmod, lpAnsiName, (LPSTR)rt, LangId); 04146 04147 UserLocalFree(lpAnsiName); 04148 04149 return hRes; 04150 } 04151 04152 /***************************************************************************\ 04153 * WOWLoadBitmapA 04154 * 04155 * 04156 \***************************************************************************/ 04157 04158 HBITMAP WOWLoadBitmapA( 04159 HINSTANCE hmod, 04160 LPCSTR lpName, 04161 LPBYTE pResData, 04162 DWORD cbResData) 04163 { 04164 LPWSTR lpUniName; 04165 HBITMAP hRet; 04166 04167 UNREFERENCED_PARAMETER(cbResData); 04168 04169 if (pResData == NULL) { 04170 04171 if (ID(lpName)) 04172 return LoadBmp(hmod, (LPCWSTR)lpName, 0, 0, 0); 04173 04174 if (!MBToWCS(lpName, -1, &lpUniName, -1, TRUE)) 04175 return NULL; 04176 04177 hRet = LoadBmp(hmod, lpUniName, 0, 0, 0); 04178 04179 UserLocalFree(lpUniName); 04180 04181 } else { 04182 04183 hRet = ConvertDIBBitmap((LPBITMAPINFOHEADER)pResData, 04184 0, 04185 0, 04186 LR_DEFAULTSIZE, 04187 NULL, 04188 NULL); 04189 } 04190 04191 return hRet; 04192 } 04193 04194 /***************************************************************************\ 04195 * WOWServerLoadCreateCursorIcon 04196 * 04197 * 04198 \***************************************************************************/ 04199 04200 HICON WowServerLoadCreateCursorIcon( 04201 HANDLE hmod, 04202 LPWSTR pszModName, 04203 DWORD dwExpWinVer, 04204 LPCWSTR lpName, 04205 DWORD cb, 04206 PVOID pResData, 04207 LPWSTR type, 04208 BOOL fClient) 04209 { 04210 HICON hRet; 04211 BOOL fIcon = (type == RT_ICON); 04212 UINT LR_Flags = LR_SHARED; 04213 04214 UNREFERENCED_PARAMETER(pszModName); 04215 UNREFERENCED_PARAMETER(dwExpWinVer); 04216 UNREFERENCED_PARAMETER(cb); 04217 UNREFERENCED_PARAMETER(fClient); 04218 04219 if (!fIcon) 04220 LR_Flags |= LR_MONOCHROME; 04221 04222 if (pResData == NULL) { 04223 04224 hRet = LoadIcoCur(hmod, 04225 lpName, 04226 type, 04227 0, 04228 0, 04229 LR_Flags | LR_DEFAULTSIZE); 04230 04231 } else { 04232 04233 hRet = ConvertDIBIcon((LPBITMAPINFOHEADER)pResData, 04234 hmod, 04235 lpName, 04236 fIcon, 04237 GetIcoCurWidth(0 , fIcon, LR_DEFAULTSIZE, 0), 04238 GetIcoCurHeight(0, fIcon, LR_DEFAULTSIZE, 0), 04239 LR_Flags); 04240 } 04241 04242 return hRet; 04243 } 04244 04245 /***************************************************************************\ 04246 * WOWServerLoadCreateMenu 04247 * 04248 * 04249 \***************************************************************************/ 04250 HMENU WowServerLoadCreateMenu( 04251 HANDLE hMod, 04252 LPCSTR lpName, 04253 CONST LPMENUTEMPLATE pmt, 04254 DWORD cb, 04255 BOOL fCallClient) 04256 { 04257 UNREFERENCED_PARAMETER(cb); 04258 UNREFERENCED_PARAMETER(fCallClient); 04259 04260 if (pmt == NULL) { 04261 return LoadMenuA(hMod, lpName); 04262 } else 04263 return CreateMenuFromResource(pmt); 04264 } 04265 04266 /***********************************************************************\ 04267 * DIBFromBitmap() 04268 * 04269 * Creates a memory block with DIB information from a physical bitmap tagged 04270 * to a specific DC. 04271 * 04272 * A DIB block consists of a BITMAPINFOHEADER + RGB colors + DIB bits. 04273 * 04274 * Returns: UserLocalAlloc pointer to DIB info. 04275 * 04276 * 03-Nov-1995 SanfordS Created. 04277 \***********************************************************************/ 04278 04279 PVOID DIBFromBitmap( 04280 HBITMAP hbmp, 04281 HDC hdc) 04282 { 04283 BITMAP bmp; 04284 LPBITMAPINFOHEADER lpbi; 04285 DWORD cbBits; 04286 DWORD cbPalette; 04287 DWORD cbTotal; 04288 WORD cBits; 04289 04290 UserAssert(hbmp); 04291 UserAssert(hdc); 04292 04293 if (GetObject(hbmp, sizeof(BITMAP), &bmp) == 0) 04294 return NULL; 04295 04296 cBits = ((WORD)bmp.bmPlanes * (WORD)bmp.bmBitsPixel); 04297 04298 TrySmallerDIB: 04299 04300 cbBits = (DWORD)WIDTHBYTES((WORD)bmp.bmWidth * cBits) * (DWORD)bmp.bmHeight; 04301 04302 cbPalette = 0; 04303 if (cBits <= 8) 04304 cbPalette = (1 << cBits) * sizeof(RGBQUAD); 04305 else 04306 cbPalette = 3 * sizeof(RGBQUAD); 04307 04308 cbTotal = sizeof(BITMAPINFOHEADER) + cbPalette + cbBits; 04309 lpbi = (LPBITMAPINFOHEADER)UserLocalAlloc(HEAP_ZERO_MEMORY, cbTotal); 04310 if (lpbi == NULL) { 04311 04312 /* 04313 * Try a smaller DIB, if we can. We can't if the DIB is mono. 04314 */ 04315 switch (cBits) { 04316 case 4: 04317 cBits = 1; 04318 break; 04319 04320 case 8: 04321 cBits = 4; 04322 break; 04323 04324 case 16: 04325 cBits = 8; 04326 break; 04327 04328 case 24: 04329 cBits = 16; 04330 break; 04331 04332 case 32: 04333 cBits = 24; 04334 break; 04335 04336 default: 04337 return NULL; // 1 or wierd. 04338 } 04339 04340 RIPMSG1(RIP_WARNING, "Not enough memory to create large color DIB, trying %d bpp.", cBits); 04341 goto TrySmallerDIB; 04342 } 04343 04344 RtlZeroMemory(lpbi, sizeof(BITMAPINFOHEADER)); 04345 lpbi->biSize = sizeof(BITMAPINFOHEADER); 04346 lpbi->biWidth = bmp.bmWidth; 04347 lpbi->biHeight = bmp.bmHeight; 04348 lpbi->biPlanes = 1; 04349 lpbi->biBitCount = cBits; 04350 04351 /* 04352 * Get old bitmap's DIB bits, using the current DC. 04353 */ 04354 GetDIBits(hdc, 04355 hbmp, 04356 0, 04357 lpbi->biHeight, 04358 ((LPSTR)lpbi) + lpbi->biSize + cbPalette, 04359 (LPBITMAPINFO)lpbi, 04360 DIB_RGB_COLORS); 04361 04362 lpbi->biClrUsed = cbPalette / sizeof(RGBQUAD); 04363 lpbi->biSizeImage = cbBits; 04364 04365 return lpbi; 04366 } 04367 04368 /***************************************************************************\ 04369 * CopyBmp 04370 * 04371 * Creates a new bitmap and copies the given bitmap to the new one, 04372 * stretching and color-converting the bits if desired. 04373 * 04374 * 03-Nov-1995 SanfordS Created. 04375 \***************************************************************************/ 04376 04377 HBITMAP CopyBmp( 04378 HBITMAP hbmpOrg, 04379 int cxNew, 04380 int cyNew, 04381 UINT LR_flags) 04382 { 04383 HBITMAP hbmNew = NULL; 04384 LPBITMAPINFOHEADER pdib; 04385 04386 RtlEnterCriticalSection(&gcsHdc); 04387 04388 if (pdib = DIBFromBitmap(hbmpOrg, ghdcBits2)) { 04389 04390 #if 0 // Win-9x comments this code out 04391 if (LR_flags & LR_COPYRETURNORG) { 04392 04393 DWORD bpp = GetIcoCurBpp(LR_flags); 04394 04395 if ((cxNew == 0 || cxNew == pdib->biWidth) && 04396 (cyNew == 0 || cyNew == pdib->biHeight) && 04397 (bpp == 0 || bpp == pdib->biBitCount)) { 04398 04399 hbmNew = hbmpOrg; 04400 } 04401 } 04402 04403 if (hbmNew == NULL) 04404 hbmNew = ConvertDIBBitmap(pdib, cxNew, cyNew, LR_flags, NULL, NULL); 04405 #endif 04406 04407 hbmNew = ConvertDIBBitmap(pdib, cxNew, cyNew, LR_flags, NULL, NULL); 04408 04409 UserLocalFree(pdib); 04410 } 04411 04412 RtlLeaveCriticalSection(&gcsHdc); 04413 04414 if ((LR_flags & LR_COPYDELETEORG) && hbmNew && (hbmNew != hbmpOrg)) 04415 DeleteObject(hbmpOrg); 04416 04417 return hbmNew; 04418 } 04419 04420 /***********************************************************************\ 04421 * CopyImageFromRes 04422 * 04423 * This is used by the LR_COPYFROMRESOURCE option. We assume that the 04424 * icon/cursor passed in is among the process list of loaded shared 04425 * icons. If we find it there, we can attempt to load the icon from 04426 * the resource to get an image that looks better than a stretched or 04427 * compressed one. 04428 * 04429 * That way we will not stretch a 32x32 icon to 16x16 if someone added 04430 * a 16x16 image to their class icon--a simple way for apps to jazz up 04431 * their appearance. 04432 * 04433 * 12-Mar-1996 ChrisWil Created. 04434 \***********************************************************************/ 04435 04436 HICON CopyImageFromRes( 04437 LPWSTR pszModName, 04438 LPWSTR pszResName, 04439 PCURSORFIND pcfSearch, 04440 UINT LR_flags) 04441 { 04442 HINSTANCE hmod; 04443 HICON hicoDst = NULL; 04444 04445 /* 04446 * Override the search-criteria if this is the user-module. By 04447 * setting these to zero, we are basically saying "don't care" for 04448 * these attributes. 04449 */ 04450 hmod = (pszModName ? WowGetModuleHandle(pszModName) : hmodUser); 04451 04452 if (hmod == hmodUser) { 04453 04454 pcfSearch->cx = 0; 04455 pcfSearch->cy = 0; 04456 pcfSearch->bpp = 0; 04457 04458 pszModName = szUSER32; 04459 } 04460 04461 /* 04462 * If a resource has been found with this name/bpp, then attempt 04463 * to load the resource with the desired dimensions. 04464 */ 04465 if (FindExistingCursorIcon(pszModName, pszResName, pcfSearch)) { 04466 04467 hicoDst = LoadIcoCur(hmod, 04468 pszResName, 04469 (LPWSTR)ULongToPtr( pcfSearch->rt ), 04470 pcfSearch->cx, 04471 pcfSearch->cy, 04472 LR_flags); 04473 } 04474 04475 return hicoDst; 04476 } 04477 04478 /***********************************************************************\ 04479 * CopyIcoCur() 04480 * 04481 * Allocates a new icon resource and transmogrifies the old icon into the 04482 * newly desired format. 04483 * 04484 * Note that if we have to stretch the icon, the hotspot area changes. For 04485 * icons, the hotspot is set to be the middle of the icon. 04486 * 04487 * Returns: 04488 * 04489 * 01-Nov-1995 SanfordS Created. 04490 * 12-Mar-1996 ChrisWil Added lookup for existing icon/cursor. 04491 \***********************************************************************/ 04492 04493 HICON CopyIcoCur( 04494 HICON hicoSrc, 04495 BOOL fIcon, 04496 int cxNew, 04497 int cyNew, 04498 UINT LR_flags) 04499 { 04500 HBITMAP hbmMaskNew; 04501 HBITMAP hbmColorNew; 04502 int cx; 04503 int cy; 04504 DWORD bpp; 04505 DWORD bppDesired; 04506 HICON hicoDst = NULL; 04507 ICONINFO ii; 04508 CURSORDATA cur; 04509 UNICODE_STRING strModName; 04510 UNICODE_STRING strResName; 04511 WCHAR awszModName[MAX_PATH]; 04512 WCHAR awszResName[MAX_PATH]; 04513 04514 /* 04515 * Extract needed info from existing icon/cursor from the kernel 04516 */ 04517 if (!NtUserGetIconSize(hicoSrc, 0, &cx, &cy)) 04518 return NULL; 04519 04520 cy >>= 1; 04521 04522 if (LR_flags & LR_CREATEDIBSECTION) 04523 LR_flags = (LR_flags & ~LR_CREATEDIBSECTION) | LR_CREATEREALDIB; 04524 04525 /* 04526 * Setup unicode-strings for calls to kernel-side. 04527 */ 04528 strModName.Length = 0; 04529 strModName.MaximumLength = MAX_PATH; 04530 strModName.Buffer = awszModName; 04531 04532 strResName.Length = 0; 04533 strResName.MaximumLength = MAX_PATH; 04534 strResName.Buffer = awszResName; 04535 04536 /* 04537 * Note: this creates copies of hbmMask and hbmColor that need to be 04538 * freed before we leave. 04539 */ 04540 if (!NtUserGetIconInfo(hicoSrc, 04541 &ii, 04542 &strModName, 04543 &strResName, 04544 &bpp, 04545 TRUE)) { 04546 04547 return NULL; 04548 } 04549 04550 cxNew = GetIcoCurWidth(cxNew, fIcon, LR_flags, cx); 04551 cyNew = GetIcoCurHeight(cyNew, fIcon, LR_flags, cy); 04552 04553 if (LR_flags & LR_COPYFROMRESOURCE) { 04554 04555 CURSORFIND cfSearch; 04556 LPWSTR pszModName; 04557 04558 /* 04559 * Setup the search criteria. 04560 */ 04561 cfSearch.hcur = hicoSrc; 04562 cfSearch.rt = PtrToUlong((fIcon ? RT_ICON : RT_CURSOR)); 04563 cfSearch.cx = cxNew; 04564 cfSearch.cy = cyNew; 04565 cfSearch.bpp = bpp; 04566 04567 /* 04568 * Copy the image. This performs a lookup for the hicoSrc. If 04569 * it is not found in the process and shared caches, then we 04570 * will proceed with copying the hicoSrc. If an icon is found 04571 * in the cache, then we will attempt to reload the image for 04572 * the best resolution possible. 04573 */ 04574 pszModName = (strModName.Length ? strModName.Buffer : NULL); 04575 04576 hicoDst = CopyImageFromRes(pszModName, 04577 strResName.Buffer, 04578 &cfSearch, 04579 LR_flags); 04580 04581 if (hicoDst) 04582 goto CleanupExit; 04583 } 04584 04585 bppDesired = GetIcoCurBpp(LR_flags); 04586 04587 if ((cxNew != cx) || 04588 (cyNew != cy) || 04589 ((bpp != 1) && (bppDesired != 0) && (bppDesired != bpp))) { 04590 04591 /* 04592 * Since we have to stretch or maybe fixup the colors just get 04593 * the DIB bits and let ConverDIBBitmap do all the magic. 04594 */ 04595 hbmMaskNew = CopyBmp(ii.hbmMask, cxNew, cyNew * 2, LR_MONOCHROME); 04596 04597 if (hbmMaskNew == NULL) 04598 goto CleanupExit; 04599 04600 hbmColorNew = NULL; 04601 04602 if (ii.hbmColor) { 04603 04604 hbmColorNew = CopyBmp(ii.hbmColor, cxNew, cyNew, LR_flags); 04605 04606 if (hbmColorNew == NULL) { 04607 DeleteObject(hbmMaskNew); 04608 goto CleanupExit; 04609 } 04610 } 04611 04612 /* 04613 * Replace ii.hbmxxx guys with our fixed up copies and delete the old. 04614 */ 04615 DeleteObject(ii.hbmMask); 04616 ii.hbmMask = hbmMaskNew; 04617 04618 if (ii.hbmColor && (ii.hbmColor != hbmColorNew)) { 04619 DeleteObject(ii.hbmColor); 04620 ii.hbmColor = hbmColorNew; 04621 } 04622 04623 /* 04624 * tweak the hotspots for changes in size. 04625 */ 04626 if (cxNew != cx) 04627 ii.xHotspot = MultDiv(ii.xHotspot, cxNew, cx); 04628 04629 if (cyNew != cy) 04630 ii.yHotspot = MultDiv(ii.yHotspot, cyNew, cy); 04631 04632 } else if (LR_flags & LR_COPYRETURNORG) { 04633 04634 hicoDst = hicoSrc; 04635 04636 CleanupExit: 04637 04638 /* 04639 * Free up the bitmaps which were created by GetIconInfo(). 04640 */ 04641 DeleteObject(ii.hbmMask); 04642 04643 if (ii.hbmColor) 04644 DeleteObject(ii.hbmColor); 04645 04646 goto Exit; 04647 } 04648 04649 /* 04650 * Build the icon/cursor object from the info. The bitmaps 04651 * are not freed in this case. 04652 */ 04653 hicoDst = (HICON)NtUserCallOneParam(0, SFI__CREATEEMPTYCURSOROBJECT); 04654 04655 if (hicoDst == NULL) 04656 goto CleanupExit; 04657 04658 RtlZeroMemory(&cur, sizeof(cur)); 04659 cur.lpName = strResName.Length ? strResName.Buffer : NULL; 04660 cur.lpModName = strModName.Length ? strModName.Buffer : NULL; 04661 cur.rt = ii.fIcon ? PTR_TO_ID(RT_ICON) : PTR_TO_ID(RT_CURSOR); 04662 cur.bpp = bpp; 04663 cur.cx = cxNew; 04664 cur.cy = cyNew * 2; 04665 cur.xHotspot = (short)ii.xHotspot; 04666 cur.yHotspot = (short)ii.yHotspot; 04667 cur.hbmMask = ii.hbmMask; 04668 cur.hbmColor = ii.hbmColor; 04669 04670 if (!_SetCursorIconData(hicoDst, &cur)) { 04671 NtUserDestroyCursor(hicoDst, CURSOR_ALWAYSDESTROY); 04672 return NULL; 04673 } 04674 04675 Exit: 04676 04677 /* 04678 * destroy the original if asked to. 04679 */ 04680 if (hicoDst != hicoSrc && (LR_flags & LR_COPYDELETEORG)) 04681 DestroyCursor(hicoSrc); 04682 04683 return hicoDst; 04684 } 04685 04686 /***********************************************************************\ 04687 * CopyImage 04688 * 04689 * Allocates a new icon resource and copies the attributes of the old icon 04690 * to the new icon. 04691 * 04692 * Returns: hIconNew 04693 * 04694 * 01-Nov-1995 SanfordS Created. 04695 \***********************************************************************/ 04696 04697 HANDLE WINAPI CopyImage( 04698 HANDLE hImage, 04699 UINT IMAGE_flag, 04700 int cxNew, 04701 int cyNew, 04702 UINT LR_flags) 04703 { 04704 if (LR_flags & ~LR_VALID) { 04705 RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "CopyImage: bad LR_flags."); 04706 return NULL; 04707 } 04708 04709 return InternalCopyImage(hImage, IMAGE_flag, cxNew, cyNew, LR_flags); 04710 } 04711 04712 /***********************************************************************\ 04713 * InternalCopyImage 04714 * 04715 * Performs the copyimage work. This is called from the callback-thunk. 04716 * 04717 \***********************************************************************/ 04718 04719 HANDLE InternalCopyImage( 04720 HANDLE hImage, 04721 UINT IMAGE_flag, 04722 int cxNew, 04723 int cyNew, 04724 UINT LR_flags) 04725 { 04726 switch (IMAGE_flag) { 04727 04728 case IMAGE_BITMAP: 04729 if (GetObjectType(hImage) != OBJ_BITMAP) { 04730 RIPMSG0(RIP_ERROR, "CopyImage: invalid bitmap"); 04731 return NULL; 04732 } 04733 04734 return (HICON)CopyBmp(hImage, cxNew, cyNew, LR_flags); 04735 04736 case IMAGE_CURSOR: 04737 case IMAGE_ICON: 04738 04739 return CopyIcoCur(hImage, 04740 (IMAGE_flag == IMAGE_ICON), 04741 cxNew, 04742 cyNew, 04743 LR_flags); 04744 } 04745 04746 RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "CopyImage: bad IMAGE_flag."); 04747 04748 return NULL; 04749 } 04750 04751 /***************************************************************************\ 04752 * RtlGetIdFromDirectory 04753 * 04754 * History: 04755 * 06-Apr-1991 ScottLu Cleaned up, make work with client/server. 04756 * 16-Nov-1995 SanfordS Now uses LookupIconIdFromDirectoryEx 04757 \***************************************************************************/ 04758 04759 int RtlGetIdFromDirectory( 04760 PBYTE presbits, 04761 BOOL fIcon, 04762 int cxDesired, 04763 int cyDesired, 04764 DWORD LR_flags, 04765 PDWORD pdwResSize) 04766 { 04767 LPNEWHEADER lpnh; 04768 LPRESDIR lprsd; 04769 UINT iImage; 04770 UINT cImage; 04771 UINT bpp; 04772 04773 /* 04774 * Make sure this is pointing to valid resource bits. 04775 */ 04776 if (presbits == NULL) 04777 return 0; 04778 04779 lpnh = (LPNEWHEADER)presbits; 04780 04781 /* 04782 * Fill in defaults. 04783 */ 04784 cxDesired = GetIcoCurWidth(cxDesired, fIcon, LR_flags, 0); 04785 cyDesired = GetIcoCurHeight(cyDesired, fIcon, LR_flags, 0); 04786 04787 bpp = GetIcoCurBpp(LR_flags); 04788 04789 /* 04790 * We'll use the first image in the directory if we can't find one 04791 * that's appropriate. 04792 */ 04793 cImage = lpnh->ResCount; 04794 lprsd = (LPRESDIR)(lpnh + 1); 04795 04796 iImage = GetBestImage(lprsd, cImage, cxDesired, cyDesired, bpp, fIcon); 04797 04798 if (iImage == cImage) 04799 iImage = 0; 04800 04801 if (pdwResSize != NULL) 04802 *pdwResSize = (lprsd + iImage)->BytesInRes; 04803 04804 return ((LPRESDIR)(lprsd + iImage))->idIcon; 04805 }

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