00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
#include "precomp.h"
00015
#pragma hdrstop
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 LPBYTE
MenuLoadWinTemplates(
00030 LPBYTE lpMenuTemplate,
00031 HMENU *phMenu)
00032 {
00033 HMENU hMenu;
00034
UINT menuFlags = 0;
00035 ULONG_PTR menuId = 0;
00036 LPWSTR lpmenuText;
00037 MENUITEMINFO mii;
00038 UNICODE_STRING str;
00039
00040
if (!(hMenu =
NtUserCreateMenu()))
00041
goto memoryerror;
00042
00043
do {
00044
00045
00046
00047
00048 menuFlags = (
UINT)(*(WORD *)lpMenuTemplate);
00049 lpMenuTemplate += 2;
00050
00051
if (menuFlags & ~MF_VALID) {
00052 RIPERR1(ERROR_INVALID_DATA, RIP_WARNING,
"Menu Flags %lX are invalid", menuFlags);
00053
goto memoryerror;
00054 }
00055
00056
00057
if (!(menuFlags & MF_POPUP)) {
00058 menuId = *(WORD *)lpMenuTemplate;
00059 lpMenuTemplate += 2;
00060 }
00061
00062 lpmenuText = (LPWSTR)lpMenuTemplate;
00063
00064
if (*lpmenuText) {
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
if ((menuFlags & MFT_OWNERDRAW)
00075 && (
GetClientInfo()->dwTIFlags &
TIF_16BIT)) {
00076 lpmenuText = (LPWSTR)ULongToPtr( (*(
DWORD UNALIGNED *)lpMenuTemplate) );
00077
00078
00079
00080 lpMenuTemplate +=
sizeof(
DWORD) -
sizeof(WCHAR);
00081 }
else {
00082
00083
00084
00085
RtlInitUnicodeString(&str, lpmenuText);
00086 lpMenuTemplate = lpMenuTemplate + str.Length;
00087 }
00088
00089 }
else {
00090 lpmenuText =
NULL;
00091 }
00092
00093
00094
00095
00096
00097 lpMenuTemplate +=
sizeof(WCHAR);
00098 lpMenuTemplate =
NextWordBoundary(lpMenuTemplate);
00099
00100 RtlZeroMemory(&mii,
sizeof(mii));
00101 mii.cbSize =
sizeof(MENUITEMINFO);
00102 mii.fMask = MIIM_ID | MIIM_STATE | MIIM_FTYPE;
00103
if (lpmenuText) {
00104 mii.fMask |= MIIM_STRING;
00105 }
00106
00107
if (menuFlags & MF_POPUP) {
00108 mii.fMask |= MIIM_SUBMENU;
00109 lpMenuTemplate =
MenuLoadWinTemplates(lpMenuTemplate,
00110 (HMENU *)&menuId);
00111
if (!lpMenuTemplate)
00112
goto memoryerror;
00113
00114 mii.hSubMenu = (HMENU)menuId;
00115 }
00116
00117
00118
00119
00120
00121
00122
if (menuFlags & MF_BITMAP) {
00123
00124
00125
00126
00127 menuFlags = (
UINT)((menuFlags | MFT_RIGHTJUSTIFY) & ~MF_BITMAP);
00128 }
00129
00130
00131
00132
00133 mii.fState = (menuFlags & MFS_OLDAPI_MASK) & ~MFS_HILITE;
00134 mii.fType = (menuFlags & MFT_OLDAPI_MASK);
00135
if (menuFlags & MFT_OWNERDRAW)
00136 {
00137 mii.fMask |= MIIM_DATA;
00138 mii.dwItemData = (ULONG_PTR) lpmenuText;
00139 lpmenuText = 0;
00140 }
00141 mii.dwTypeData = (LPWSTR) lpmenuText;
00142 mii.cch = (
UINT)-1;
00143 mii.wID = (
UINT)menuId;
00144
00145
if (!
NtUserThunkedMenuItemInfo(hMenu,
MFMWFP_NOITEM,
TRUE,
TRUE,
00146 &mii, lpmenuText ? &str :
NULL)) {
00147
if (menuFlags & MF_POPUP)
00148
NtUserDestroyMenu(mii.hSubMenu);
00149
goto memoryerror;
00150 }
00151
00152 }
while (!(menuFlags & MF_END));
00153
00154 *phMenu = hMenu;
00155
return lpMenuTemplate;
00156
00157 memoryerror:
00158
if (hMenu !=
NULL)
00159
NtUserDestroyMenu(hMenu);
00160 *phMenu =
NULL;
00161
return NULL;
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 PMENUITEMTEMPLATE2
MenuLoadChicagoTemplates(
00177 PMENUITEMTEMPLATE2 lpMenuTemplate,
00178 HMENU *phMenu,
00179 WORD wResInfo,
00180 UINT mftRtl)
00181 {
00182 HMENU hMenu;
00183 HMENU hSubMenu;
00184
long menuId = 0;
00185 LPWSTR lpmenuText;
00186 MENUITEMINFO mii;
00187 UNICODE_STRING str;
00188
DWORD dwHelpID;
00189
00190
if (!(hMenu =
NtUserCreateMenu()))
00191
goto memoryerror;
00192
00193
do {
00194
if (!(wResInfo & MFR_POPUP)) {
00195
00196
00197
00198
00199 lpMenuTemplate = (PMENUITEMTEMPLATE2)(((LPBYTE)lpMenuTemplate) -
00200
sizeof(lpMenuTemplate->dwHelpID));
00201 dwHelpID = 0;
00202 }
else
00203 dwHelpID = lpMenuTemplate->dwHelpID;
00204
00205 menuId = lpMenuTemplate->menuId;
00206
00207 RtlZeroMemory(&mii,
sizeof(mii));
00208 mii.cbSize =
sizeof(MENUITEMINFO);
00209 mii.fMask = MIIM_ID | MIIM_STATE | MIIM_FTYPE ;
00210
00211 mii.fType = lpMenuTemplate->fType | mftRtl;
00212
if (mii.fType & ~MFT_MASK) {
00213 RIPERR1(ERROR_INVALID_DATA, RIP_WARNING,
"Menu Type flags %lX are invalid", mii.fType);
00214
goto memoryerror;
00215 }
00216
00217 mii.fState = lpMenuTemplate->fState;
00218
if (mii.fState & ~MFS_MASK) {
00219 RIPERR1(ERROR_INVALID_DATA, RIP_WARNING,
"Menu State flags %lX are invalid", mii.fState);
00220
goto memoryerror;
00221 }
00222
00223 wResInfo = lpMenuTemplate->wResInfo;
00224
if (wResInfo & ~(MF_END | MFR_POPUP)) {
00225 RIPERR1(ERROR_INVALID_DATA, RIP_WARNING,
"Menu ResInfo flags %lX are invalid", wResInfo);
00226
goto memoryerror;
00227 }
00228
00229
if (dwHelpID) {
00230
NtUserSetMenuContextHelpId(hMenu,dwHelpID);
00231 }
00232
if (lpMenuTemplate->mtString[0]) {
00233 lpmenuText = lpMenuTemplate->mtString;
00234 mii.fMask |= MIIM_STRING;
00235 }
else {
00236 lpmenuText =
NULL;
00237 }
00238
RtlInitUnicodeString(&str, lpmenuText);
00239
00240 mii.dwTypeData = (LPWSTR) lpmenuText;
00241
00242
00243
00244
00245 lpMenuTemplate = (PMENUITEMTEMPLATE2)
00246 (((LPBYTE)lpMenuTemplate) +
00247
sizeof(MENUITEMTEMPLATE2) +
00248 ((str.Length + 3) & ~3));
00249
00250
if (mii.fType & MFT_OWNERDRAW)
00251 {
00252 mii.fMask |= MIIM_DATA;
00253 mii.dwItemData = (ULONG_PTR) mii.dwTypeData;
00254 mii.dwTypeData = 0;
00255 }
00256
00257
00258
00259
00260
00261
if (mii.fType & MFT_RIGHTORDER)
00262 {
00263 mftRtl = MFT_RIGHTORDER;
00264
NtUserSetMenuFlagRtoL(hMenu);
00265 }
00266
00267
if (wResInfo & MFR_POPUP) {
00268 mii.fMask |= MIIM_SUBMENU;
00269 lpMenuTemplate =
MenuLoadChicagoTemplates(lpMenuTemplate,
00270 &hSubMenu, MFR_POPUP, mftRtl);
00271
if (lpMenuTemplate ==
NULL)
00272
goto memoryerror;
00273 mii.hSubMenu = hSubMenu;
00274 }
00275
00276
if (mii.fType & MFT_BITMAP) {
00277
00278
00279
00280
00281 mii.fType = (mii.fType | MFT_RIGHTJUSTIFY) & ~MFT_BITMAP;
00282 }
00283
00284 mii.cch = (
UINT)-1;
00285 mii.wID = menuId;
00286
if (!
NtUserThunkedMenuItemInfo(hMenu,
MFMWFP_NOITEM,
TRUE,
TRUE,
00287 &mii, &str)) {
00288
if (wResInfo & MFR_POPUP)
00289
NtUserDestroyMenu(mii.hSubMenu);
00290
goto memoryerror;
00291 }
00292 wResInfo &= ~MFR_POPUP;
00293 }
while (!(wResInfo & MFR_END));
00294
00295 *phMenu = hMenu;
00296
return lpMenuTemplate;
00297
00298 memoryerror:
00299
if (hMenu !=
NULL)
00300
NtUserDestroyMenu(hMenu);
00301 *phMenu =
NULL;
00302
return NULL;
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 HMENU
CreateMenuFromResource(
00320 LPBYTE lpMenuTemplate)
00321 {
00322 HMENU hMenu =
NULL;
00323
UINT menuTemplateVersion;
00324
UINT menuTemplateHeaderSize;
00325
00326
00327
00328
00329
00330 menuTemplateVersion = *((WORD *)lpMenuTemplate)++;
00331
if (menuTemplateVersion > 1) {
00332 RIPMSG0(RIP_WARNING,
"Menu Version number > 1");
00333
return NULL;
00334 }
00335 menuTemplateHeaderSize = *((WORD *)lpMenuTemplate)++;
00336 lpMenuTemplate += menuTemplateHeaderSize;
00337
switch (menuTemplateVersion) {
00338
case 0:
00339
MenuLoadWinTemplates(lpMenuTemplate, &hMenu);
00340
break;
00341
00342
case 1:
00343
MenuLoadChicagoTemplates((PMENUITEMTEMPLATE2)lpMenuTemplate, &hMenu, 0, 0);
00344
break;
00345 }
00346
return hMenu;
00347 }
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 BOOL SetMenu(
00359 HWND hwnd,
00360 HMENU hmenu)
00361 {
00362
return NtUserSetMenu(hwnd, hmenu,
TRUE);
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378 HMENU
CommonLoadMenu(
00379 HINSTANCE hmod,
00380 HANDLE hResInfo
00381 )
00382 {
00383 HANDLE h;
00384 PVOID p;
00385 HMENU hMenu =
NULL;
00386
00387
if (h =
LOADRESOURCE(hmod, hResInfo)) {
00388
00389
if (p =
LOCKRESOURCE(h, hmod)) {
00390
00391 hMenu =
CreateMenuFromResource(p);
00392
00393
UNLOCKRESOURCE(h, hmod);
00394 }
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 }
00406
00407
return (hMenu);
00408 }
00409
00410 HMENU WINAPI
LoadMenuA(
00411 HINSTANCE hmod,
00412 LPCSTR lpName)
00413 {
00414 HANDLE hRes;
00415
00416
if (hRes =
FINDRESOURCEA(hmod, (LPSTR)lpName, (LPSTR)RT_MENU))
00417
return CommonLoadMenu(hmod, hRes);
00418
else
00419
return NULL;
00420 }
00421
00422 HMENU WINAPI
LoadMenuW(
00423 HINSTANCE hmod,
00424 LPCWSTR lpName)
00425 {
00426 HANDLE hRes;
00427
00428
if (hRes =
FINDRESOURCEW(hmod, (LPWSTR)lpName, RT_MENU))
00429
return CommonLoadMenu(hmod, hRes);
00430
else
00431
return NULL;
00432 }
00433
00434
00435
00436
00437
00438
00439 BOOL InternalInsertMenuItem (HMENU hMenu, UINT uID, BOOL fByPosition, LPCMENUITEMINFO lpmii)
00440 {
00441
return ThunkedMenuItemInfo(hMenu, uID, fByPosition,
TRUE, (LPMENUITEMINFOW)lpmii,
FALSE);
00442 }
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 BOOL ValidateMENUITEMINFO(LPMENUITEMINFO lpmiiIn, LPMENUITEMINFO lpmii, DWORD dwAPICode)
00455 {
00456
00457 VALIDATIONFNNAME(
ValidateMENUITEMINFO)
00458
BOOL fOldApp;
00459
00460
if (lpmiiIn ==
NULL) {
00461 VALIDATIONFAIL(lpmiiIn);
00462 }
00463
00464
00465
00466
00467
00468 fOldApp = (lpmiiIn->cbSize == SIZEOFMENUITEMINFO95);
00469 UserAssert(SIZEOFMENUITEMINFO95 <
sizeof(MENUITEMINFO));
00470 RtlCopyMemory(lpmii, lpmiiIn, SIZEOFMENUITEMINFO95);
00471
if (fOldApp) {
00472 lpmii->cbSize =
sizeof(MENUITEMINFO);
00473 lpmii->hbmpItem =
NULL;
00474 }
else if (lpmiiIn->cbSize ==
sizeof(MENUITEMINFO)) {
00475 lpmii->hbmpItem = lpmiiIn->hbmpItem;
00476 }
else {
00477 VALIDATIONFAIL(lpmiiIn->cbSize);
00478 }
00479
00480
00481
if (lpmii->fMask & ~MIIM_MASK) {
00482 VALIDATIONFAIL(lpmii->fMask);
00483 }
else if ((lpmii->fMask & MIIM_TYPE)
00484 && (lpmii->fMask & (MIIM_FTYPE | MIIM_STRING | MIIM_BITMAP))) {
00485
00486
00487
00488 VALIDATIONFAIL(lpmii->fMask);
00489 }
00490
00491
00492
00493
00494
if (dwAPICode ==
MENUAPI_GET) {
00495
00496
00497
00498
00499
00500
00501
00502
if (lpmii->fMask & MIIM_TYPE) {
00503 lpmii->fMask |= MIIM_FTYPE | MIIM_BITMAP | MIIM_STRING;
00504 lpmii->hbmpItem =
NULL;
00505 }
00506
return TRUE;
00507 }
00508
00509
00510
00511
00512
if (lpmii->fMask & MIIM_TYPE) {
00513 lpmii->fMask |= MIIM_FTYPE;
00514 }
00515
00516
if (lpmii->fMask & MIIM_FTYPE) {
00517
if (lpmii->fType & ~MFT_MASK) {
00518 VALIDATIONFAIL(lpmii->fType);
00519 }
00520
00521
00522
00523
00524
00525
00526
if (lpmii->fMask & MIIM_TYPE) {
00527
if (lpmii->fType & MFT_BITMAP) {
00528
00529
00530
00531
00532
00533
00534 lpmii->fMask |= MIIM_BITMAP | MIIM_STRING;
00535 lpmii->hbmpItem = (HBITMAP)lpmii->dwTypeData;
00536 lpmii->dwTypeData = 0;
00537 }
else if (!(lpmii->fType & MFT_NONSTRING)) {
00538
00539
00540
00541
00542
00543
00544 lpmii->fMask |= MIIM_BITMAP | MIIM_STRING;
00545 lpmii->hbmpItem =
NULL;
00546 }
00547 }
else if (lpmii->fType & MFT_BITMAP) {
00548
00549
00550
00551 VALIDATIONFAIL(lpmii->fType);
00552 }
00553 }
00554
00555
if ((lpmii->fMask & MIIM_STATE) && (lpmii->fState & ~MFS_MASK)){
00556 VALIDATIONFAIL(lpmii->fState);
00557 }
00558
00559
if (lpmii->fMask & MIIM_CHECKMARKS) {
00560
if ((lpmii->hbmpChecked !=
NULL) && !GdiValidateHandle((HBITMAP)lpmii->hbmpChecked)) {
00561 VALIDATIONFAIL(lpmii->hbmpChecked);
00562 }
00563
if ((lpmii->hbmpUnchecked !=
NULL) && !GdiValidateHandle((HBITMAP)lpmii->hbmpUnchecked)) {
00564 VALIDATIONFAIL(lpmii->hbmpUnchecked);
00565 }
00566 }
00567
00568
if (lpmii->fMask & MIIM_SUBMENU) {
00569
if ((lpmii->hSubMenu !=
NULL) && !
VALIDATEHMENU(lpmii->hSubMenu)) {
00570 VALIDATIONFAIL(lpmii->hSubMenu);
00571 }
00572 }
00573
00574
00575
00576
00577
if (lpmii->fMask & MIIM_BITMAP) {
00578
if ((lpmii->hbmpItem != HBMMENU_CALLBACK)
00579 && (lpmii->hbmpItem >= HBMMENU_MAX)
00580 && !GdiValidateHandle(lpmii->hbmpItem)) {
00581
00582
00583
00584
00585
if (((HBITMAP)LOWORD(HandleToUlong(lpmii->hbmpItem)) >= HBMMENU_MAX) || !
IS_PTR(lpmii->hbmpItem)) {
00586 VALIDATIONFAIL(lpmii->hbmpItem);
00587 }
00588 }
00589 }
00590
00591
00592
00593
00594
00595
return TRUE;
00596
00597 VALIDATIONERROR(
FALSE);
00598 }
00599
00600
00601
00602
00603
00604
00605
00606
00607 BOOL ValidateMENUINFO(LPCMENUINFO lpmi, DWORD dwAPICode)
00608 {
00609 VALIDATIONFNNAME(
ValidateMENUINFO)
00610
00611
if (lpmi ==
NULL) {
00612 VALIDATIONFAIL(lpmi);
00613 }
00614
00615
if (lpmi->cbSize !=
sizeof(MENUINFO)) {
00616 VALIDATIONFAIL(lpmi->cbSize);
00617 }
00618
00619
if (lpmi->fMask & ~MIM_MASK) {
00620 VALIDATIONFAIL(lpmi->fMask);
00621 }
00622
00623
00624
00625
00626
if (dwAPICode ==
MENUAPI_GET){
00627
return TRUE;
00628 }
00629
00630
if ((lpmi->fMask & MIM_STYLE) && (lpmi->dwStyle & ~MNS_VALID)) {
00631 VALIDATIONFAIL(lpmi->dwStyle);
00632 }
00633
00634
if (lpmi->fMask & MIM_BACKGROUND) {
00635
if ((lpmi->hbrBack !=
NULL)
00636 && !GdiValidateHandle((HBRUSH)lpmi->hbrBack)) {
00637
00638 VALIDATIONFAIL(lpmi->hbrBack);
00639 }
00640 }
00641
00642
return TRUE;
00643
00644 VALIDATIONERROR(
FALSE);
00645 }
00646
00647
00648
00649
00650
00651
00652 BOOL GetMenuInfo(HMENU hMenu, LPMENUINFO lpmi)
00653 {
00654
PMENU pMenu;
00655
00656
if (!
ValidateMENUINFO(lpmi,
MENUAPI_GET)) {
00657
return FALSE;
00658 }
00659
00660 pMenu =
VALIDATEHMENU(hMenu);
00661
if (pMenu ==
NULL) {
00662
return FALSE;
00663 }
00664
00665
if (lpmi->fMask & MIM_STYLE) {
00666 lpmi->dwStyle = pMenu->
fFlags & MNS_VALID;
00667 }
00668
00669
if (lpmi->fMask & MIM_MAXHEIGHT) {
00670 lpmi->cyMax = pMenu->
cyMax;
00671 }
00672
00673
if (lpmi->fMask & MIM_BACKGROUND) {
00674 lpmi->hbrBack = pMenu->
hbrBack;
00675 }
00676
00677
if (lpmi->fMask & MIM_HELPID) {
00678 lpmi->dwContextHelpID = pMenu->
dwContextHelpId;
00679 }
00680
00681
if (lpmi->fMask & MIM_MENUDATA) {
00682 lpmi->dwMenuData = KERNEL_ULONG_PTR_TO_ULONG_PTR(pMenu->
dwMenuData);
00683 }
00684
00685
return TRUE;
00686 }