test: dlgbegin.c Source File

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

# dlgbegin.c

Go to the documentation of this file.

    00001 /***************************************************************************\
    00002 *
    00003 *  DLGBEGIN.C -
    00004 *
    00005 * Copyright (c) 1985 - 1999, Microsoft Corporation
    00006 *
    00007 *      Dialog Initialization Routines
    00008 *
    00009 * ??-???-???? mikeke    Ported from Win 3.0 sources
    00010 * 12-Feb-1991 mikeke    Added Revalidation code
    00011 \***************************************************************************/
    00012
    00013 #include "precomp.h"
    00014 #pragma hdrstop
    00015
    00016 BOOL ValidateCallback(HANDLE h);
    00017
    00018 CONST WCHAR szEDITCLASS[] = TEXT("Edit");
    00019
    00020 /*
    00021  * Fixed, hard coded literal for Dialog hacks
    00022  */
    00023 const WCHAR gwszShellFont[]  = L"MS Shell Dlg";
    00024 const WCHAR gwszShellFont2[] = L"MS Shell Dlg 2";
    00025
    00026
    00027 #ifdef USE_MIRRORING
    00028 #define MIRRORED_HWND(hwnd)   (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
    00029 #endif
    00030 /***************************************************************************\
    00031 * DefShortToInt
    00032 *
    00033 * Avoid sign extending 16 bit CW2_USEDEFAULT. We need this because the
    00034 *  dialog resource template uses SHORT fields to store the coordinates
    00035 *  but CreateWindow wants INT values.
    00036 *
    00037 * History:
    00038 * 12/04/96 GerardoB Created
    00039 \***************************************************************************/
    00040 __inline int DefShortToInt (short s)
    00041 {
    00042     if (s == (short)CW2_USEDEFAULT) {
    00043         return (int)(DWORD)(WORD)CW2_USEDEFAULT;
    00044     } else {
    00045         return (int)s;
    00046     }
    00047 }
    00048 /***************************************************************************\
    00049 * BYTE FAR *SkipSz(lpsz)
    00050 *
    00051 * History:
    00052 \***************************************************************************/
    00053
    00054 PBYTE SkipSz(
    00055     UTCHAR *lpsz)
    00056 {
    00057     if (*lpsz == 0xFF)
    00058         return (PBYTE)lpsz + 4;
    00059
    00060     while (*lpsz++ != 0) ;
    00061
    00062     return (PBYTE)lpsz;
    00063 }
    00064
    00065 PBYTE WordSkipSz(
    00066     UTCHAR *lpsz)
    00067 {
    00068     PBYTE pb = SkipSz(lpsz);
    00069     return NextWordBoundary(pb);
    00070 }
    00071
    00072 PBYTE DWordSkipSz(
    00073     UTCHAR *lpsz)
    00074 {
    00075     PBYTE pb = SkipSz(lpsz);
    00076     return NextDWordBoundary(pb);
    00077 }
    00078
    00079
    00080 /***************************************************************************\
    00081 *
    00082 * IsFontNotGood()
    00083 *
    00084 * If this is a low res device, we need to check if the
    00085 * font we're creating is smaller than the system font.
    00086 *
    00087 \***************************************************************************/
    00088 __inline BOOLEAN IsFontNotGood(LPWSTR szTempBuffer, LPCWSTR lpStrSubst, TEXTMETRIC* ptm)
    00089 {
    00090     //
    00091     // For FarEast version, we will allow the font smaller than system font.
    00092     //
    00093     return _wcsicmp(szTempBuffer, lpStrSubst) ||
    00094                 (!IS_ANY_DBCS_CHARSET(ptm->tmCharSet) &&
    00095                     (SYSMET(CXICON) < 32 || SYSMET(CYICON) < 32) &&
    00096                     ptm->tmHeight < gpsi->cySysFontChar);
    00097 }
    00098
    00099 // --------------------------------------------------------------------------
    00100 //  GetCharsetEnumProc()
    00101 //
    00102 //  This gets the best asian font for a dialog box.
    00103 //
    00104 //  1996-Sep-11 hideyukn     Port from Win95-FE
    00105 // --------------------------------------------------------------------------
    00106 int CALLBACK GetCharsetEnumProc(
    00107     LPLOGFONT     lpLogFont,
    00108     LPTEXTMETRIC  lptm,
    00109     DWORD         nType,
    00110     LPARAM        lpData)
    00111 {
    00112     UNREFERENCED_PARAMETER(lptm);
    00113     UNREFERENCED_PARAMETER(nType);
    00114
    00115     //
    00116     // Use other than FIXED pitch sysfont when the face name isn't specified.
    00117     //
    00118     if ((lpLogFont->lfPitchAndFamily & 3) == FIXED_PITCH)
    00119     {
    00120         if (!lstrcmpi(lpLogFont->lfFaceName,L"System") ||
    00121             !lstrcmpi(lpLogFont->lfFaceName,L"@System"))
    00122             return TRUE; // try to get another system font metric
    00123     }
    00124
    00125     ((LPLOGFONT)lpData)->lfCharSet = lpLogFont->lfCharSet;
    00126     ((LPLOGFONT)lpData)->lfPitchAndFamily = lpLogFont->lfPitchAndFamily;
    00127     return FALSE;
    00128 }
    00129
    00130 /*
    00131  * Get a character set based on System's ANSI CODEPAGE
    00132  */
    00133 UINT GetACPCharSet()
    00134 {
    00135     static UINT charset = (UINT)~0;
    00136     CHARSETINFO csInfo;
    00137
    00138     if (charset != (UINT)~0) {
    00139         return charset;
    00140     }
    00141
    00142     // Sundown: In the TCI_SRCCODEPAGE case, the GetACP() return value is zero-extended.
    00143     if (!TranslateCharsetInfo((DWORD*)UIntToPtr( GetACP() ), &csInfo, TCI_SRCCODEPAGE)) {
    00144         return DEFAULT_CHARSET;
    00145     }
    00146     charset = csInfo.ciCharset;
    00147     UserAssert(charset != (UINT)~0);
    00148     return csInfo.ciCharset;
    00149 }
    00150
    00151 #if 0
    00152 BYTE GetCharsetFromResourceLang(LCID lcid)
    00153 {
    00154     CHARSETINFO csInfo;
    00155
    00156     if (!TranslateCharsetInfo((DWORD *)lcid, &csInfo, TCI_SRCLOCALE))
    00157         return DEFAULT_CHARSET;
    00158     return csInfo.ciCharset;
    00159 }
    00160 #endif
    00161
    00162 /***************************************************************************\
    00163 *
    00164 * CreateDlgFont()
    00165 *
    00166 * Create the dialog font described at the given location in a resource
    00167 *
    00168 \***************************************************************************/
    00169
    00170 #define GET_DESKTOP_CHARSET()   (GetTextCharset(hdcDlg))
    00171
    00172 //
    00173 // Reserved Dlg resource version number
    00174 //
    00175 #define DLGRSC_VER_NT5COMPAT_RESERVE    10
    00176
    00177 BOOL FixupDlgLogFont(
    00178         HDC hdcDlg,
    00179         LPLOGFONT lpLogFont,
    00180         LPDLGTEMPLATE2 lpdt,
    00181         BOOLEAN fUseShellFont2,
    00182         BOOLEAN* pfWillTryDefaultCharset)
    00183 {
    00184     switch (lpdt->wDlgVer) {
    00185     case 0:
    00186         // DIALOG statement, which only has a facename.
    00187         // The new applications are not supposed to use DIALOG statement,
    00188         // they should use DIALOGEX instead.
    00189         lpLogFont->lfWeight  = FW_BOLD;
    00190         if (!fUseShellFont2) {
    00191             lpLogFont->lfCharSet = (BYTE)GET_DESKTOP_CHARSET();
    00192             *pfWillTryDefaultCharset = TRUE;
    00193         }
    00194         break;
    00195     case 1:
    00196         //
    00197         // Win4 compatible DLG template
    00198         //
    00199         if (!fUseShellFont2) {
    00200             if (IS_DBCS_ENABLED()) {
    00201                 if (lpLogFont->lfCharSet == ANSI_CHARSET) {
    00202                     //
    00203                     // When resource compiler generates dialog resource data
    00204                     // from DIALOGEX template, it can specify 'charset'. but
    00205                     // optional, if it is not specified, it will be filled
    00206                     // with 0 (ANSI charset). But, on localized version,
    00207                     // User might guess the default will be localized-charset
    00208                     //
    00209                     // [Dialog Resource File]
    00210                     //
    00211                     // DIALOGEX ...
    00212                     // ...
    00213                     // FONT pointsize, typeface, [weight], [italic], [charset]
    00214                     //
    00215                     // #100182
    00216                     // Bogus hack:
    00217                     // Some FE fonts started to have ANSI_CHARSET so the first attept would succeed.
    00218                     // We should enumerate the charset from the beginning.
    00219                     lpLogFont->lfCharSet = DEFAULT_CHARSET;
    00220                     RIPMSG0(RIP_VERBOSE, "No proper CharSet information in DIALOGEX");
    00221                 }
    00222             }
    00223             /*
    00224              * Note: Dialog resource version 2.0 or later has not been supported on
    00225              * Windows 95 and 98. As of Apr/98 we decided not to deploy this new feature
    00226              * in the standard tools. Still, NT 5 supports this new feature, preparing
    00227              * the future transition to do the right thing.
    00228              */
    00229             else if (lpLogFont->lfCharSet == ANSI_CHARSET) {
    00230                 // If the first attempt fail, we'll enumerate the charset for the given facename
    00231                 *pfWillTryDefaultCharset = TRUE;
    00232             }
    00233             else if (lpLogFont->lfCharSet == DEFAULT_CHARSET) {
    00234                 lpLogFont->lfCharSet = (BYTE)GET_DESKTOP_CHARSET();
    00235             }
    00236         }
    00237         break;
    00238     default:
    00239         if (lpdt->wDlgVer <= DLGRSC_VER_NT5COMPAT_RESERVE) {
    00240             // we do nothing for the new resource compiler (>= 2.0),
    00241             // since this version of dialogs are guarunteed to have
    00242             // the proper character set for the dialog font.
    00243         }
    00244         else {
    00245             RIPMSG1(RIP_WARNING, "Version %d resource is not supported.", lpdt->wDlgVer);
    00246             return FALSE;
    00247         }
    00248         break;
    00249     }
    00250
    00251     return TRUE;
    00252 }
    00253
    00254 VOID FixupDlgFaceName(
    00255         LPLOGFONT lpLogFont,
    00256         BOOLEAN fUseShellFont,
    00257         BOOLEAN fUseShellFont2,
    00258         LPCWSTR lpStrSubst)
    00259 {
    00260     if (fUseShellFont2) {
    00261         //
    00262         // OK, we use "MS Shell Dlg 2" as a face name.
    00263         //
    00264         wcsncpycch(lpLogFont->lfFaceName, gwszShellFont2, ARRAY_SIZE(gwszShellFont2));
    00265     }
    00266     else {
    00267         //
    00268         // Otherwise, get the face name from the dialog template.
    00269         //
    00270         wcsncpycch(lpLogFont->lfFaceName, lpStrSubst, sizeof(lpLogFont->lfFaceName) / sizeof(WCHAR));
    00271     }
    00272
    00273     //
    00274     // "MS Shell Dlg" and "MS Shell Dlg2" should have native character set ---
    00275     //
    00276     if (fUseShellFont || fUseShellFont2) {
    00277         lpLogFont->lfCharSet = (BYTE)GetACPCharSet();
    00278     }
    00279 }
    00280
    00281
    00282 HFONT CreateDlgFont(HDC hdcDlg, LPWORD FAR *lplpstr, LPDLGTEMPLATE2 lpdt, DWORD dwExpWinVer, UINT fSCDLGFlags)
    00283 {
    00284     LOGFONT     LogFont;
    00285     int         fontheight, fheight;
    00286     HFONT       hOldFont, hFont;
    00287     WCHAR       szTempBuffer[LF_FACESIZE];
    00288     LPCWSTR     lpStrSubst;
    00289     TEXTMETRIC  tm;
    00290     // Font hacks
    00291     BOOLEAN     fDeleteFont;
    00292     BOOLEAN     fWillTryDefaultCharset = FALSE;
    00293     BOOLEAN     fUseShellFont, fUseShellFont2;
    00294
    00295     UNREFERENCED_PARAMETER(dwExpWinVer);
    00296     UNREFERENCED_PARAMETER(fSCDLGFlags);
    00297
    00298     fheight = fontheight = (SHORT)(*((WORD *) *lplpstr)++);
    00299
    00300     if (fontheight == 0x7FFF) {
    00301         // a 0x7FFF height is our special code meaning use the message box font
    00302         GetObject(gpsi->hMsgFont, sizeof(LOGFONT), &LogFont);
    00303         return CreateFontIndirect(&LogFont);
    00304     }
    00305
    00306     //
    00307     // The dialog template contains a font description! Use it.
    00308     //
    00309
    00310     // Fill the LogFont with default values
    00311     RtlZeroMemory(&LogFont, sizeof(LOGFONT));
    00312
    00313     fontheight = -MultDiv(fontheight, gpsi->dmLogPixels, 72);
    00314     LogFont.lfHeight = fontheight;
    00315
    00316     if (lpdt->wDlgVer) {
    00317         //
    00318         // If it's DIALOGEX, additional info should be read from
    00319         // the template.
    00320         //
    00321         LogFont.lfWeight  = *((WORD FAR *) *lplpstr)++;
    00322         LogFont.lfItalic  = *((BYTE FAR *) *lplpstr)++;
    00323         LogFont.lfCharSet = *((BYTE FAR *) *lplpstr)++;
    00324     }
    00325
    00326     //
    00327     // Per shell team request, the dialog who has DS_SETFONT
    00328     // *and* DS_FIXEDSYS (=> DS_SHELLFONT2) should have a font
    00329     // "MS Shell Dlg 2".
    00330     //
    00331     lpStrSubst = *lplpstr;
    00332
    00333     //
    00334     // Set the pointer to the next item.
    00335     //
    00336     *lplpstr = (WORD*)DWordSkipSz(*lplpstr);
    00337
    00338     fUseShellFont = _wcsicmp(lpStrSubst, gwszShellFont) == 0;
    00339
    00340     //
    00341     // Later shell team request again, to use "Dlg 2" font only
    00342     // when facename in the dialog template is "MS Shell Dlg".
    00343     //
    00344     fUseShellFont2 = fUseShellFont &&
    00345         (lpdt->style & DS_SHELLFONT) == DS_SHELLFONT && Is400Compat(dwExpWinVer) && lpdt->wDlgVer != 0;
    00346
    00347     if (fUseShellFont2) {
    00348         TAGMSG0(DBGTAG_IMM, "CreateDlgFont: fUseShellFont2=TRUE");
    00349     }
    00350
    00351     //
    00352     // Prepare the font character set.
    00353     //
    00354     if (!FixupDlgLogFont(hdcDlg, &LogFont, lpdt, fUseShellFont2, &fWillTryDefaultCharset)) {
    00355         return NULL;
    00356     }
    00357
    00358     //
    00359     // Prepare the font facename.
    00360     //
    00361     FixupDlgFaceName(&LogFont, fUseShellFont, fUseShellFont2, lpStrSubst);
    00362
    00363     if (lpdt->wDlgVer < 2 && lpdt->style & DS_3DLOOK)
    00364         LogFont.lfWeight = FW_NORMAL;
    00365
    00366 TryDefaultCharset:
    00367     if (LogFont.lfCharSet == DEFAULT_CHARSET) {
    00368         //
    00369         // Get character set for given facename.
    00370         //
    00371         EnumFonts(hdcDlg, LogFont.lfFaceName,
    00372                   (FONTENUMPROC)GetCharsetEnumProc, (LPARAM)(&LogFont));
    00373         //
    00374         // We already tried default charset.
    00375         //
    00376         fWillTryDefaultCharset = FALSE;
    00377     }
    00378
    00379     //
    00380     // [Windows 3.1 FarEast version did this...]
    00381     //
    00382     // Use FW_NORMAL as default for DIALOG template. For DIALOGEX
    00383     // template, we need to respect the value in the template.
    00384     //
    00385     if ((!(lpdt->wDlgVer)) && // not DIALOGEX template ?
    00386         (IS_ANY_DBCS_CHARSET(LogFont.lfCharSet)) && // any FarEast font ?
    00387         (LogFont.lfWeight != FW_NORMAL)) { // already FW_NORMAL ?
    00388
    00389         //
    00390         // Set weight to FW_NORMAL.
    00391         //
    00392         LogFont.lfWeight = FW_NORMAL;
    00393     }
    00394
    00395     if (!(hFont = CreateFontIndirect((LPLOGFONT) &LogFont)))
    00396         return(NULL);
    00397
    00398     fDeleteFont = FALSE;
    00399
    00400     if ((hOldFont = SelectFont(hdcDlg, hFont)) == NULL) {
    00401         fDeleteFont = TRUE;
    00402     }
    00403     else {
    00404         //
    00405         // If this dialog has DS_SHELLFONT style, or the font is
    00406         // "MS Shell Dlg", we don't judge the font integrity,
    00407         // for they have been given the ACP based character set.
    00408         //
    00409         if (!fUseShellFont) {
    00410             if (!GetTextMetrics(hdcDlg, &tm)) {
    00411                 RIPMSG0(RIP_WARNING, "CreateDlgFont: GetTextMetrics failed");
    00412                 fDeleteFont = TRUE;
    00413             }
    00414             else {
    00415                 GetTextFaceAliasW(hdcDlg, sizeof(szTempBuffer)/sizeof(WCHAR), szTempBuffer);
    00416
    00417                 //
    00418                 // If this is a low res device, we need to check if the
    00419                 // font we're creating is smaller than the system font.
    00420                 // If so, just use the system font.
    00421                 //
    00422                 if (IsFontNotGood(szTempBuffer, lpStrSubst, &tm)) {
    00423                     //
    00424                     // Couldn't find a font with the height or facename
    00425                     // the app wanted so use the system font instead. Note
    00426                     // that we need to make sure the app knows it is
    00427                     // getting the system font via the WM_SETFONT message
    00428                     // so we still need to act as if a new font is being
    00429                     // sent to the dialog box.
    00430                     //
    00431                     fDeleteFont = TRUE;
    00432                 }
    00433             }
    00434         }
    00435
    00436         UserAssert(hOldFont != NULL);
    00437         SelectFont(hdcDlg, hOldFont);
    00438     }
    00439
    00440     if (fDeleteFont) {
    00441         DeleteFont(hFont);
    00442         //
    00443         // Font is deleted, Prepare for reTry...
    00444         //
    00445         hFont = NULL;
    00446     }
    00447
    00448     // Font hack:
    00449     //
    00450     // 1. We fail to create font.
    00451     // 2. We did *NOT* try to enumerate charset, yet.
    00452     // 3. We want to try to enumerate charset
    00453     //
    00454     // if all of answer is 'Yes', we will try...
    00455     //
    00456     if (hFont == NULL && fWillTryDefaultCharset) {
    00457         //
    00458         // Try DEFAULT_CHARSET.
    00459         //
    00460         LogFont.lfCharSet = DEFAULT_CHARSET;
    00461         goto TryDefaultCharset;
    00462     }
    00463
    00464     return hFont;
    00465 }
    00466
    00467 #undef GET_DESKTOP_CHARSET
    00468
    00469 #define CD_VISIBLE          0x01
    00470 #define CD_GLOBALEDIT       0x02
    00471 #define CD_USERFONT         0x04
    00472 #define CD_SETFOREGROUND    0x08
    00473 #define CD_USEDEFAULTX      0x10
    00474 #define CD_USEDEFAULTCX     0x20
    00475
    00476
    00477 /***************************************************************************\
    00478 * GetDialogMonitor
    00479 *
    00480 * Gets the monitor a dialog should be created on.
    00481 *
    00482 * Params:
    00483 *     hwndOwner - the owner of the dialog. May be NULL.
    00484 *
    00485 * History:
    00486 * 10-Oct-1996 adams     Created.
    00487 \***************************************************************************/
    00488
    00489 PMONITOR
    00490 GetDialogMonitor(HWND hwndOwner, DWORD dwFlags)
    00491 {
    00492     PMONITOR    pMonitor;
    00493     PWND        pwnd;
    00494     HWND        hwndForeground;
    00495     DWORD       pid;
    00496
    00497     UserAssert(dwFlags == MONITOR_DEFAULTTONULL ||
    00498                dwFlags == MONITOR_DEFAULTTOPRIMARY);
    00499
    00500     pMonitor = NULL;
    00501     if (hwndOwner) {
    00502         pwnd = ValidateHwnd(hwndOwner);
    00503         if (pwnd && GETFNID(pwnd) != FNID_DESKTOP) {
    00504             pMonitor = _MonitorFromWindow(pwnd, MONITOR_DEFAULTTOPRIMARY);
    00505         }
    00506     } else {
    00507         /*
    00508          * HACK!  They passed in no owner and are creating a top level
    00509          * dialog window.  Does this process own the foreground window?
    00510          * If so, pin to that window's monitor.  That way 16-bit apps
    00511          * will work mostly as expected, and old multithreaded dudes just
    00512          * might too.  Especially the shell, for whom many system UI pieces
    00513          * pop up random dialogs inside of API calls.
    00514          */
    00515
    00516         hwndForeground = NtUserGetForegroundWindow();
    00517         if (hwndForeground) {
    00518             GetWindowThreadProcessId(hwndForeground, &pid);
    00519             if (pid == HandleToUlong(NtCurrentTeb()->ClientId.UniqueProcess)) {
    00520                 pwnd = ValidateHwnd(hwndForeground);
    00521                 if (pwnd) {
    00522                     pMonitor = _MonitorFromWindow(pwnd, MONITOR_DEFAULTTOPRIMARY);
    00523                 }
    00524             }
    00525         }
    00526     }
    00527
    00528     if (!pMonitor && dwFlags == MONITOR_DEFAULTTOPRIMARY) {
    00529         pMonitor = GetPrimaryMonitor();
    00530     }
    00531
    00532     return pMonitor;
    00533 }
    00534
    00535
    00536
    00537 /***************************************************************************\
    00538 * InternalCreateDialog
    00539 *
    00540 * Creates a dialog from a template. Uses passed in menu if there is one,
    00541 * destroys menu if creation failed. Server portion of
    00542 * CreateDialogIndirectParam.
    00543 *
    00544 * WARNING: This function cannot create any windows before creating the dialog
    00545 *           window. Otherwise, MFC apps will break because their hook assumes
    00546 *           the dialog is the first window to be created.
    00547 *
    00548 * History:
    00549 * 04-10-91 ScottLu
    00550 * 04-17-91 Mikehar Win31 Merge
    00551 \***************************************************************************/
    00552
    00553 HWND InternalCreateDialog(
    00554     HANDLE hmod,
    00555     LPDLGTEMPLATE lpdt,
    00556     DWORD cb,
    00557     HWND hwndOwner,
    00558     DLGPROC lpfnDialog,
    00559     LPARAM lParam,
    00560     UINT fSCDLGFlags)
    00561 {
    00562     HWND                hwnd;
    00563     HWND                hwnd2;
    00564     PWND                pwnd;
    00565     HWND                hwndNewFocus;
    00566     HWND                hwndEditFirst = NULL;
    00567     RECT                rc;
    00568     WORD                w;
    00569     UTCHAR              *lpszMenu,
    00570                         *lpszClass,
    00571                         *lpszText,
    00572                         *lpCreateParams,
    00573                         *lpStr;
    00574     int                 cxChar,
    00575                         cyChar;
    00576     BOOL                f40Compat;
    00577     HFONT               hNewFont = NULL;
    00578     HFONT               hOldFont;
    00579     LPDLGITEMTEMPLATE   lpdit;
    00580     HMENU               hMenu;
    00581     BOOL                fSuccess;
    00582     BOOL                fWowWindow;
    00583     HANDLE              hmodCreate;
    00584     LPBYTE              lpCreateParamsData;
    00585     DLGTEMPLATE2        dt;
    00586     DLGITEMTEMPLATE2    dit;
    00587     DWORD               dwExpWinVer;
    00588     DWORD               dsStyleOld;
    00589     DWORD               bFlags = 0;
    00590     HDC                 hdcDlg;
    00591     LARGE_STRING        strClassName;
    00592     PLARGE_STRING       pstrClassName;
    00593     LARGE_STRING        strWindowName;
    00594     PMONITOR            pMonitor;
    00595
    00596     UNREFERENCED_PARAMETER(cb);
    00597
    00598     ConnectIfNecessary();
    00599
    00600     UserAssert(!(fSCDLGFlags & ~(SCDLG_CLIENT|SCDLG_ANSI|SCDLG_NOREVALIDATE|SCDLG_16BIT)));    // These are the only valid flags
    00601
    00602     /*
    00603      * Is this a Win4 extended dialog?
    00604      */
    00605     if (((LPDLGTEMPLATE2)lpdt)->wSignature == 0xffff) {
    00606
    00607         UserAssert(((LPDLGTEMPLATE2)lpdt)->wDlgVer <= DLGRSC_VER_NT5COMPAT_RESERVE);
    00608         RtlCopyMemory(&dt, lpdt, sizeof dt);
    00609     } else {
    00610         dt.wDlgVer = 0;
    00611         dt.wSignature = 0;
    00612         dt.dwHelpID = 0;
    00613         dt.dwExStyle = lpdt->dwExtendedStyle;
    00614         dt.style = lpdt->style;
    00615         dt.cDlgItems = lpdt->cdit;
    00616         dt.x = lpdt->x;
    00617         dt.y = lpdt->y;
    00618         dt.cx = lpdt->cx;
    00619         dt.cy = lpdt->cy;
    00620     }
    00621
    00622     /*
    00623      * If this is called from wow code, then the loword of hmod != 0.
    00624      * In this case, allow any DS_ style bits that were passed in win3.1
    00625      * to be legal in win32. Case in point: 16 bit quark xpress passes the
    00626      * same bit as the win32 style DS_SETFOREGROUND. Also, VC++ sample
    00627      * "scribble" does the same thing.
    00628      *
    00629      * For win32 apps test the DS_SETFOREGROUND bit; wow apps are not set
    00630      * foreground (this is the new NT semantics)
    00631      * We have to let no "valid" bits through because apps depend on them
    00632      * bug 5232.
    00633      */
    00634     dsStyleOld = LOWORD(dt.style);
    00635
    00636     /*
    00637      * If the app is Win4 or greater, require correct dialog style bits.
    00638      * Prevents conflicts with new bits introduced in Chicago
    00639      */
    00640     dwExpWinVer = GETEXPWINVER(hmod);
    00641
    00642     if ( f40Compat = Is400Compat(dwExpWinVer) ) {
    00643         dt.style &= (DS_VALID40 | 0xffff0000);
    00644
    00645         //
    00646         // For old applications:
    00647         //      If DS_COMMONDIALOG isn't set, don't touch DS_3DLOOK style
    00648         // bit.  If it's there, it stays there.  If not, not.  That way old
    00649         // apps which pass in their own templates, not commdlg's, don't get
    00650         // forced 3D.
    00651         //      If DS_COMMONDIALOG is there, remove DS_3DLOOK.
    00652         //
    00653         // For new applications:
    00654         //      Force 3D always.
    00655         //
    00656         if (GETAPPVER() < VER40) {
    00657             if (dt.style & DS_COMMONDIALOG) {
    00658                 dt.style &= ~DS_3DLOOK;
    00659                 dsStyleOld &= ~DS_3DLOOK;
    00660             }
    00661         } else {
    00662             dt.style |= DS_3DLOOK;
    00663             dsStyleOld |= DS_3DLOOK;
    00664         }
    00665     } else {
    00666 #if DBG
    00667         if (dt.style != (dt.style & (DS_VALID31 | DS_3DLOOK | 0xffff0000))) {
    00668             RIPMSG1(RIP_WARNING, "CreateDialog: stripping invalid bits %lX", dt.style);
    00669         }
    00670 #endif // DBG
    00671
    00672
    00673         /*
    00674          * Don't strip off bits for old apps, they depend on this.  Especially 16 bit MFC apps!
    00675          *
    00676          * dt.dwStyle &= (DS_VALID31 | 0xffff0000);
    00677          */
    00678     }
    00679
    00680     if (LOWORD((ULONG_PTR)hmod) == 0) {
    00681         if (dt.style & DS_SETFOREGROUND)
    00682             bFlags |= CD_SETFOREGROUND;
    00683     }
    00684
    00685     if (dsStyleOld != LOWORD(dt.style))
    00686     {
    00687
    00688         RIPMSG1(f40Compat ? RIP_ERROR : RIP_WARNING,
    00689                 "Bad dialog style bits (%x) - please remove.",
    00690                 LOWORD(dt.style));
    00691         // Fail new apps that pass in bogus bits!
    00692
    00693         if (f40Compat) {
    00694             return NULL;
    00695         }
    00696     }
    00697
    00698     if ( dt.style & DS_MODALFRAME) {
    00699         dt.dwExStyle |= WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE;
    00700     }
    00701
    00702     if (( dt.style & DS_CONTEXTHELP) && f40Compat) {
    00703         dt.dwExStyle |= WS_EX_CONTEXTHELP;
    00704     }
    00705
    00706     if (dt.style & DS_CONTROL) {
    00707         // Captions and system menus aren't allowed on "control" dialogs.
    00708         // And strip DS_SYSMODAL.
    00709         dt.style &= ~(WS_CAPTION | WS_SYSMENU | DS_SYSMODAL);
    00710     } else if (dt.style & WS_DLGFRAME) {
    00711         // Add on window edge same way that CreateWindowEx() will
    00712         dt.dwExStyle |= WS_EX_WINDOWEDGE;
    00713     }
    00714
    00715     if (dt.style & DS_SYSMODAL) {
    00716         dt.dwExStyle |= WS_EX_TOPMOST;
    00717     }
    00718
    00719     if (!(dt.style & WS_CHILD) || (dt.style & DS_CONTROL)) {
    00720         // only a control parent if it's not a child dialog or if it's
    00721         // explicitly marked as a recursive dialog
    00722         dt.dwExStyle |= WS_EX_CONTROLPARENT;
    00723     }
    00724
    00725     if (dt.x == (short)CW2_USEDEFAULT) {
    00726         bFlags |= CD_USEDEFAULTX;
    00727         dt.x = 0;
    00728     }
    00729
    00730     if (dt.cx == (short)CW2_USEDEFAULT) {
    00731         bFlags |= CD_USEDEFAULTCX;
    00732         dt.cx = 0;
    00733     } else if (dt.cx < 0) {
    00734         dt.cx = 0;
    00735     }
    00736
    00737     if (dt.cy < 0) {
    00738         dt.cy = 0;
    00739     }
    00740
    00741
    00742     // If there's a menu name string, load it.
    00743     lpszMenu = (LPWSTR)(((PBYTE)(lpdt)) + (dt.wDlgVer ? sizeof(DLGTEMPLATE2):sizeof(DLGTEMPLATE)));
    00744
    00745     /*
    00746      * If the menu id is expressed as an ordinal and not a string,
    00747      * skip all 4 bytes to get to the class string.
    00748      */
    00749     w = *(LPWORD)lpszMenu;
    00750
    00751     /*
    00752      * If there's a menu name string, load it.
    00753      */
    00754     if (w != 0) {
    00755         if ((hMenu = LoadMenu(hmod, (w == 0xFFFF) ?
    00756                 MAKEINTRESOURCE(*(WORD *)((PBYTE)lpszMenu + 2)) : lpszMenu)) == NULL) {
    00757             RIPMSG0(RIP_WARNING, "ServerCreateDialog() failed: couldn't load menu");
    00758             goto DeleteFontAndMenuAndFail;
    00759         }
    00760     } else {
    00761         hMenu = NULL;
    00762     }
    00763
    00764     if (w == 0xFFFF) {
    00765         lpszClass = (LPWSTR)((LPBYTE)lpszMenu + 4);
    00766     } else {
    00767         lpszClass = (UTCHAR *)WordSkipSz(lpszMenu);
    00768     }
    00769
    00770     lpszText = (UTCHAR *)WordSkipSz(lpszClass);
    00771
    00772     lpStr = (UTCHAR *)WordSkipSz(lpszText);
    00773
    00774     hdcDlg = CreateCompatibleDC(NULL);
    00775     if (hdcDlg == NULL)
    00776         goto DeleteFontAndMenuAndFail;
    00777
    00778     if (dt.style & DS_SETFONT) {
    00779         hNewFont = CreateDlgFont(hdcDlg, &lpStr, &dt, dwExpWinVer, fSCDLGFlags);
    00780         bFlags |= CD_USERFONT;
    00781         lpdit = (LPDLGITEMTEMPLATE) NextDWordBoundary(lpStr);
    00782     } else if (Is400Compat(dwExpWinVer) && (dt.style & DS_FIXEDSYS)) {
    00783
    00784         //
    00785         // B#2078 -- WISH for fixed width system font in dialog.  We need
    00786         // to tell the dialog that it's using a font different from the
    00787         // standard system font, so set CD_USERFONT bit.
    00788         //
    00789         // We need the 400 compat. check for CorelDraw, since they use
    00790         // this style bit for their own purposes.
    00791         //
    00792         hNewFont = GetStockObject(SYSTEM_FIXED_FONT);
    00793         bFlags |= CD_USERFONT;
    00794         lpdit = (LPDLGITEMTEMPLATE)NextDWordBoundary(lpStr);
    00795     } else {
    00796         lpdit = (LPDLGITEMTEMPLATE)NextDWordBoundary(lpStr);
    00797     }
    00798
    00799     /*
    00800      * If the application requested a particular font and for some
    00801      * reason we couldn't find it, we just use the system font.  BUT we
    00802      * need to make sure we tell him he gets the system font.  Dialogs
    00803      * which never request a particular font get the system font and we
    00804      * don't bother telling them this (via the WM_SETFONT message).
    00805      */
    00806
    00807     // Is it anything other than the default system font?  If we can't get
    00808     // enough memory to select in the new font specified, just use the system
    00809     // font.
    00810     if (hNewFont && (hOldFont = SelectFont(hdcDlg, hNewFont))) {
    00811         // Get the ave character width and height to be used
    00812         cxChar = GdiGetCharDimensions(hdcDlg, NULL, &cyChar);
    00813
    00814         SelectFont(hdcDlg, hOldFont);
    00815         if (cxChar == 0) {
    00816             RIPMSG0(RIP_WARNING, "InternalCreateDialog: GdiGetCharDimensions failed");
    00817             goto UseSysFontMetrics;
    00818         }
    00819     }
    00820     else
    00821     {
    00822         if (hNewFont || (bFlags & CD_USERFONT))
    00823             hNewFont = ghFontSys;
    00824
    00825 UseSysFontMetrics:
    00826         cxChar = gpsi->cxSysFontChar;
    00827         cyChar = gpsi->cySysFontChar;
    00828     }
    00829     DeleteDC(hdcDlg);
    00830
    00831     if (dt.style & WS_VISIBLE) {
    00832         bFlags |= CD_VISIBLE;
    00833         dt.style &= ~WS_VISIBLE;
    00834     }
    00835
    00836     if (!(dt.style & DS_LOCALEDIT)) {
    00837         bFlags |= CD_GLOBALEDIT;
    00838     }
    00839
    00840     /* Figure out dimensions of real window
    00841      */
    00842     rc.left = rc.top = 0;
    00843     rc.right = XPixFromXDU(dt.cx, cxChar);
    00844     rc.bottom = YPixFromYDU(dt.cy, cyChar);
    00845
    00846     _AdjustWindowRectEx(&rc, dt.style, w, dt.dwExStyle);
    00847
    00848     dt.cx = (SHORT)(rc.right - rc.left);
    00849     dt.cy = (SHORT)(rc.bottom - rc.top);
    00850
    00851     if ((dt.style & DS_CENTERMOUSE) && SYSMET(MOUSEPRESENT) && f40Compat) {
    00852         pMonitor = _MonitorFromPoint(gpsi->ptCursor, MONITOR_DEFAULTTONULL);
    00853         UserAssert(pMonitor);
    00854         *((LPPOINT)&rc.left) = gpsi->ptCursor;
    00855         rc.left -= (dt.cx / 2);
    00856         rc.top  -= (dt.cy / 2);
    00857     } else {
    00858         BOOL fNoDialogMonitor;
    00859
    00860         pMonitor = GetDialogMonitor(hwndOwner, MONITOR_DEFAULTTONULL);
    00861         fNoDialogMonitor = pMonitor ? FALSE : TRUE;
    00862         if (!pMonitor) {
    00863             pMonitor = GetPrimaryMonitor();
    00864         }
    00865
    00866         if ((dt.style & (DS_CENTER | DS_CENTERMOUSE)) && f40Compat) {
    00867             /*
    00868              * Center to the work area of the owner monitor.
    00869              */
    00870             rc.left = (pMonitor->rcWork.left + pMonitor->rcWork.right - dt.cx) / 2;
    00871             rc.top  = (pMonitor->rcWork.top + pMonitor->rcWork.bottom - dt.cy) / 2;
    00872         } else {
    00873             rc.left = XPixFromXDU(dt.x, cxChar);
    00874             rc.top = YPixFromYDU(dt.y, cyChar);
    00875
    00876             if (!(dt.style & DS_ABSALIGN) && hwndOwner) {
    00877                 /*
    00878                  * Offset relative coordinates to the owner window. If it is
    00879                  * a child window, there is nothing to do.
    00880                  */
    00881                 if ((HIWORD(dt.style) & MaskWF(WFTYPEMASK)) != MaskWF(WFCHILD)) {
    00882                     //This is will considre rc.left form the right hand side of the owner window if it a mirrored one.
    00883                     ClientToScreen(hwndOwner, (LPPOINT)&rc.left);
    00884
    00885 #ifdef USE_MIRRORING
    00886                     //It is not chiled then do Visual ClientToScreen
    00887                     //i.e. rc.left it is form the left hand side of the owner window
    00888                     if (MIRRORED_HWND(hwndOwner)) {
    00889                         rc.left -= dt.cx;
    00890                     }
    00891 #endif
    00892
    00893                 }
    00894             } else {
    00895                 /*
    00896                  * Position the dialog in screen coordinates. If the dialog's
    00897                  * owner is on a different monitor than specified in the
    00898                  * template, move the dialog to the owner window. If the owner
    00899                  * doesn't exist, then use the monitor from the dialog's
    00900                  * template.
    00901                  */
    00902
    00903                 PMONITOR    pMonitorTemplate;
    00904                 RECT        rcTemplate;
    00905
    00906                 rcTemplate.left  = rc.left;
    00907                 rcTemplate.top   = rc.top;
    00908                 rcTemplate.right  = rc.left + dt.cx;
    00909                 rcTemplate.bottom = rc.top + dt.cy;
    00910
    00911                 pMonitorTemplate = _MonitorFromRect(&rcTemplate, MONITOR_DEFAULTTOPRIMARY);
    00912                 if (fNoDialogMonitor) {
    00913                     pMonitor = pMonitorTemplate;
    00914                 } else if (pMonitorTemplate != pMonitor) {
    00915                     rc.left += pMonitor->rcMonitor.left - pMonitorTemplate->rcMonitor.left;
    00916                     rc.top  += pMonitor->rcMonitor.top  - pMonitorTemplate->rcMonitor.top;
    00917                 }
    00918             }
    00919         }
    00920     }
    00921
    00922     rc.right  = rc.left + dt.cx;
    00923     rc.bottom = rc.top  + dt.cy;
    00924
    00925     // If the right or bottom coordinate has overflowed, then pin it back to
    00926     // a valid rectangle.  Likely to happen if a minimized window is the owner of
    00927     // the dialog.
    00928     if (rc.left > rc.right || rc.top > rc.bottom) {
    00929         OffsetRect(&rc, -dt.cx, -dt.cy);
    00930     }
    00931
    00932    //
    00933     // Need to do this for ALL dialogs, not just top-level, since we used
    00934     // to in 3.1.
    00935     //
    00936
    00937     // Clip top level dialogs within working area
    00938     // Start child dialogs at least at (0, 0)
    00939     RepositionRect(pMonitor, &rc, dt.style, dt.dwExStyle);
    00940
    00941     dt.x  = (SHORT)((bFlags & CD_USEDEFAULTX) ? CW2_USEDEFAULT : rc.left);
    00942     dt.y  = (SHORT)(rc.top);
    00943     dt.cx = (SHORT)((bFlags & CD_USEDEFAULTCX) ? CW2_USEDEFAULT : rc.right - rc.left);
    00944     dt.cy = (SHORT)(rc.bottom - rc.top);
    00945
    00946     if (*lpszClass != 0) {
    00947         if (IS_PTR(lpszClass)) {
    00948             RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&strClassName,
    00949                     lpszClass, (UINT)-1);
    00950             pstrClassName = &strClassName;
    00951         } else {
    00952             pstrClassName = (PLARGE_STRING)lpszClass;
    00953         }
    00954     } else {
    00955         pstrClassName = (PLARGE_STRING)DIALOGCLASS;
    00956     }
    00957
    00958     RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&strWindowName,
    00959             lpszText, (UINT)-1);
    00960
    00961     UserAssert((dt.dwExStyle & WS_EX_MDICHILD) == 0);
    00962     hwnd = NtUserCreateWindowEx(
    00963             dt.dwExStyle | ((fSCDLGFlags & SCDLG_ANSI) ? WS_EX_ANSICREATOR : 0),
    00964             pstrClassName,
    00965             &strWindowName,
    00966             dt.style,
    00967             DefShortToInt(dt.x),
    00968             dt.y,
    00969             DefShortToInt(dt.cx),
    00970             dt.cy,
    00971             hwndOwner,
    00972             hMenu,
    00973             hmod,
    00974             (LPVOID)NULL,
    00975             dwExpWinVer);
    00976
    00977     if (hwnd == NULL) {
    00978         RIPMSG0(RIP_WARNING, "CreateDialog() failed: couldn't create window");
    00979 DeleteFontAndMenuAndFail:
    00980         if (hMenu != NULL)
    00981             NtUserDestroyMenu(hMenu);
    00982         /*
    00983          * Only delete the font if we didn't grab it
    00984          * from the dialog font cache.
    00985          */
    00986         if ((hNewFont != NULL)) {
    00987             DeleteObject(hNewFont);
    00988         }
    00989         return NULL;
    00990     }
    00991
    00992     pwnd = ValidateHwnd(hwnd);
    00993
    00994     // tell WOW the hDlg of the Window just created BEFORE they get any messages
    00995     // at WOW32!w32win16wndprocex
    00996     if(fSCDLGFlags & SCDLG_16BIT) {
    00997         TellWOWThehDlg(hwnd);
    00998     }
    00999
    01000     /*
    01001      * Before anything happens with this window, we need to mark it as a
    01002      * dialog window!!!! So do that.
    01003      */
    01004     if (pwnd == NULL || !ValidateDialogPwnd(pwnd))
    01005         goto DeleteFontAndMenuAndFail;
    01006
    01007     if (dt.dwHelpID) {
    01008         NtUserSetWindowContextHelpId(hwnd, dt.dwHelpID);
    01009     }
    01010
    01011     /*
    01012      * Set up the system menu on this dialog box if it has one.
    01013      */
    01014     if (TestWF(pwnd, WFSYSMENU)) {
    01015
    01016         /*
    01017          * For a modal dialog box with a frame and caption, we want to
    01018          * delete the unselectable items from the system menu.
    01019          */
    01020         UserAssert(HIBYTE(WFSIZEBOX) == HIBYTE(WFMINBOX));
    01021         UserAssert(HIBYTE(WFMINBOX) == HIBYTE(WFMAXBOX));
    01022         if (!TestWF(pwnd, WFSIZEBOX | WFMINBOX | WFMAXBOX)) {
    01023
    01024             NtUserCallHwndLock(hwnd, SFI_XXXSETDIALOGSYSTEMMENU);
    01025         } else {
    01026
    01027             /*
    01028              * We have to give this dialog its own copy of the system menu
    01029              * in case it modifies the menu.
    01030              */
    01031             NtUserGetSystemMenu(hwnd, FALSE);
    01032         }
    01033     }
    01034
    01035     /*
    01036      * Set fDisabled to FALSE so EndDialog will Enable if dialog is ended
    01037      * before returning to DialogBox (or if modeless).
    01038      */
    01039     PDLG(pwnd)->fDisabled = FALSE;
    01040
    01041     PDLG(pwnd)->cxChar = cxChar;
    01042     PDLG(pwnd)->cyChar = cyChar;
    01043     PDLG(pwnd)->lpfnDlg = lpfnDialog;
    01044     PDLG(pwnd)->fEnd = FALSE;
    01045     PDLG(pwnd)->result = IDOK;
    01046
    01047     /*
    01048      * Need to remember Unicode status.
    01049      */
    01050     if (fSCDLGFlags & SCDLG_ANSI) {
    01051         PDLG(pwnd)->flags |= DLGF_ANSI;
    01052     }
    01053
    01054     /*
    01055      * Have to do a callback here for WOW apps.  WOW needs what's in lParam
    01056      * before the dialog gets any messages.
    01057      */
    01058
    01059     /*
    01060      * If the app is a Wow app then the Lo Word of the hInstance is the
    01061      * 16-bit hInstance.  Set the lParam, which no-one should look at
    01062      * but the app, to the 16 bit value
    01063      */
    01064     if (LOWORD((ULONG_PTR)hmod) != 0) {
    01065         fWowWindow = TRUE;
    01066     } else {
    01067         fWowWindow = FALSE;
    01068     }
    01069
    01070     /*
    01071      * If a user defined font is used, save the handle so that we can delete
    01072      * it when the dialog is destroyed.
    01073      */
    01074     if (bFlags & CD_USERFONT) {
    01075
    01076         PDLG(pwnd)->hUserFont = hNewFont;
    01077
    01078         if (lpfnDialog != NULL) {
    01079             /*
    01080              * Tell the dialog that it will be using this font...
    01081              */
    01082             SendMessageWorker(pwnd, WM_SETFONT, (WPARAM)hNewFont, 0L, FALSE);
    01083         }
    01084     }
    01085
    01086     if (!dt.wDlgVer) {
    01087         dit.dwHelpID = 0;
    01088     }
    01089
    01090     /*
    01091      * Loop through the dialog controls, doing a CreateWindowEx() for each of
    01092      * them.
    01093      */
    01094     while (dt.cDlgItems-- != 0) {
    01095         DWORD dwExpWinVer2;
    01096
    01097         if (dt.wDlgVer) {
    01098             RtlCopyMemory(&dit, lpdit, sizeof dit);
    01099         } else {
    01100             dit.dwHelpID = 0;
    01101             dit.dwExStyle = lpdit->dwExtendedStyle;
    01102             dit.style = lpdit->style;
    01103             dit.x = lpdit->x;
    01104             dit.y = lpdit->y;
    01105             dit.cx = lpdit->cx;
    01106             dit.cy = lpdit->cy;
    01107             dit.dwID = lpdit->id;
    01108         }
    01109
    01110         dit.x = XPixFromXDU(dit.x, cxChar);
    01111         dit.y = YPixFromYDU(dit.y, cyChar);
    01112         dit.cx = XPixFromXDU(dit.cx, cxChar);
    01113         dit.cy = YPixFromYDU(dit.cy, cyChar);
    01114
    01115         lpszClass = (LPWSTR)(((PBYTE)(lpdit)) + (dt.wDlgVer ? sizeof(DLGITEMTEMPLATE2):sizeof(DLGITEMTEMPLATE)));
    01116
    01117         /*
    01118          * If the first WORD is 0xFFFF the second word is the encoded class name index.
    01119          * Use it to look up the class name string.
    01120          */
    01121         if (*(LPWORD)lpszClass == 0xFFFF) {
    01122             lpszText = lpszClass + 2;
    01123             lpszClass = (LPWSTR)(gpsi->atomSysClass[*(((LPWORD)lpszClass)+1) & ~CODEBIT]);
    01124         } else {
    01125             lpszText = (UTCHAR *)SkipSz(lpszClass);
    01126         }
    01127         lpszText = (UTCHAR *)NextWordBoundary(lpszText); // UINT align lpszText
    01128
    01129         dit.dwExStyle |= WS_EX_NOPARENTNOTIFY;
    01130
    01131         //
    01132         // Replace flat borders with 3D ones for DS_3DLOOK dialogs
    01133         // We test the WINDOW style, not the template style now.  This is so
    01134         // that 4.0 apps--who get 3D stuff automatically--can turn it off on
    01135         // create if they want.
    01136         //
    01137
    01138         //
    01139         // HACK!
    01140         // Treat DS_3DLOOK combos like they have a WS_EX_CLIENTEDGE.  Why
    01141         // should we have to draw the borders of a combobox ourselves?
    01142         // We can't do the same thing for WS_BORDER though becaues of
    01143         // PC Fools--they use the presence of WS_BORDER to distinguish
    01144         // between lists and combos.
    01145         //
    01146
    01147         if (TestWF(pwnd, DF3DLOOK)) {
    01148             if (    (dit.style & WS_BORDER) ||
    01149                     (lpszClass == MAKEINTRESOURCE(gpsi->atomSysClass[ICLS_COMBOBOX]))) {
    01150
    01151                 dit.style &= ~WS_BORDER;
    01152                 dit.dwExStyle |= WS_EX_CLIENTEDGE;
    01153             }
    01154         }
    01155
    01156         /*
    01157          * Get pointer to additional data.  lpszText can point to an encoded
    01158          * ordinal number for some controls (e.g.  static icon control) so
    01159          * we check for that here.
    01160          */
    01161         if (*(LPWORD)lpszText == 0xFFFF) {
    01162             lpCreateParams = (LPWSTR)((PBYTE)lpszText + 4);
    01163             strWindowName.Buffer = lpszText;
    01164             strWindowName.Length = 4;
    01165             strWindowName.MaximumLength = 4;
    01166             strWindowName.bAnsi = FALSE;
    01167         } else {
    01168             lpCreateParams = (LPWSTR)((PBYTE)WordSkipSz(lpszText));
    01169             RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&strWindowName,
    01170                     lpszText, (UINT)-1);
    01171         }
    01172
    01173         /*
    01174          * If control is edit control and caller wants global storage
    01175          * of edit text, allocate object in WOW and pass instance
    01176          * handle to CreateWindowEx().
    01177          */
    01178         if (fWowWindow && (bFlags & CD_GLOBALEDIT) &&
    01179                ((!IS_PTR(lpszClass) &&
    01180                     PTR_TO_ID(lpszClass) == (ATOM)(gpsi->atomSysClass[ICLS_EDIT])) ||
    01181                (IS_PTR(lpszClass) &&
    01182                     (wcscmp(lpszClass, szEDITCLASS) == 0)))) {
    01183
    01184             /*
    01185              * Allocate only one global object (first time we see editctl.)
    01186              */
    01187             if (!(PDLG(pwnd)->hData)) {
    01188                 PDLG(pwnd)->hData = GetEditDS();
    01189                 if (!(PDLG(pwnd)->hData))
    01190                     goto NoCreate;
    01191             }
    01192
    01193             hmodCreate = PDLG(pwnd)->hData;
    01194             dwExpWinVer2 = GETEXPWINVER(hmodCreate);
    01195         } else {
    01196             hmodCreate = hmod;
    01197             dwExpWinVer2 = dwExpWinVer;
    01198         }
    01199
    01200 #if DBG
    01201         if ((dit.dwExStyle & WS_EX_ANSICREATOR) != 0) {
    01202             RIPMSG1(RIP_WARNING, "Bad WS_EX_ style 0x%x for a control in the dialog",
    01203                     dit.dwExStyle);
    01204         }
    01205 #endif // DBG
    01206
    01207         /*
    01208          * Get pointer to additional data.
    01209          *
    01210          * For WOW, instead of pointing lpCreateParams at the CreateParams
    01211          * data, set lpCreateParams to whatever DWORD is stored in the 32-bit
    01212          * DLGTEMPLATE's CreateParams.  WOW has already made sure that that
    01213          * 32-bit value is indeed a 16:16 pointer to the CreateParams in the
    01214          * 16-bit DLGTEMPLATE.
    01215          */
    01216
    01217         if (*lpCreateParams) {
    01218             lpCreateParamsData = (LPBYTE)lpCreateParams;
    01219             if (fWowWindow || fSCDLGFlags & SCDLG_16BIT) {
    01220                 lpCreateParamsData =
    01221                     (LPBYTE)ULongToPtr( *(UNALIGNED DWORD *) /* Sundown WOW: zero-extension */
    01222                     (lpCreateParamsData + sizeof(WORD)) );
    01223             }
    01224         } else {
    01225             lpCreateParamsData = NULL;
    01226         }
    01227
    01228         /*
    01229          * If the dialog template specifies a menu ID then TestwndChild(pwnd)
    01230          * must be TRUE or CreateWindowEx will think the ID is an hMenu rather
    01231          * than an ID (in a dialog template you'll never have an hMenu).
    01232          * However for compatibility reasons we let it go if the ID = 0.
    01233          */
    01234         if (dit.dwID) {
    01235             /*
    01236              * This makes TestwndChild(pwnd) on this window return TRUE.
    01237              */
    01238             dit.style |= WS_CHILD;
    01239             dit.style &= ~WS_POPUP;
    01240         }
    01241
    01242         if (IS_PTR(lpszClass)) {
    01243             RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&strClassName,
    01244                     lpszClass, (UINT)-1);
    01245             pstrClassName = &strClassName;
    01246         } else {
    01247             pstrClassName = (PLARGE_STRING)lpszClass;
    01248         }
    01249         UserAssert((dit.dwExStyle & WS_EX_MDICHILD) == 0);
    01250
    01251         hwnd2 = NtUserCreateWindowEx(
    01252                 dit.dwExStyle | ((fSCDLGFlags & SCDLG_ANSI) ? WS_EX_ANSICREATOR : 0),
    01253                 pstrClassName,
    01254                 &strWindowName,
    01255                 dit.style,
    01256                 DefShortToInt(dit.x),
    01257                 dit.y,
    01258                 DefShortToInt(dit.cx),
    01259                 dit.cy,
    01260                 hwnd,
    01261                 (HMENU)LongToHandle( dit.dwID ),
    01262                 hmodCreate,
    01263                 lpCreateParamsData,
    01264                 dwExpWinVer2);
    01265
    01266         if (hwnd2 == NULL) {
    01267 NoCreate:
    01268             /*
    01269              * Couldn't create the window -- return NULL.
    01270              */
    01271             if (!TestWF(pwnd, DFNOFAILCREATE)) {
    01272                 RIPMSG0(RIP_WARNING, "CreateDialog() failed: couldn't create control");
    01273                 NtUserDestroyWindow(hwnd);
    01274                 return NULL;
    01275             }
    01276         } else {
    01277
    01278             if (dit.dwHelpID) {
    01279                 NtUserSetWindowContextHelpId(hwnd2, dit.dwHelpID);
    01280             }
    01281
    01282         /*
    01283          * If it is a not a default system font, set the font for all the
    01284          * child windows of the dialogbox.
    01285          */
    01286             if (hNewFont != NULL) {
    01287                 SendMessage(hwnd2, WM_SETFONT, (WPARAM)hNewFont, 0L);
    01288             }
    01289
    01290         /*
    01291          * Result gets ID of last (hopefully only) defpushbutton.
    01292          */
    01293             if (SendMessage(hwnd2, WM_GETDLGCODE, 0, 0L) & DLGC_DEFPUSHBUTTON) {
    01294                 PDLG(pwnd)->result = dit.dwID;
    01295             }
    01296
    01297         }
    01298         /*
    01299          * Point at next item template
    01300          */
    01301         lpdit = (LPDLGITEMTEMPLATE)NextDWordBoundary(
    01302                 (LPBYTE)(lpCreateParams + 1) + *lpCreateParams);
    01303     }
    01304
    01305     if (!TestWF(pwnd, DFCONTROL)) {
    01306         PWND pwndT = _GetNextDlgTabItem(pwnd, NULL, FALSE);
    01307         hwndEditFirst = HW(pwndT);
    01308     }
    01309
    01310     if (lpfnDialog != NULL) {
    01311         fSuccess = (BOOL)SendMessageWorker(pwnd, WM_INITDIALOG,
    01312                                (WPARAM)hwndEditFirst, lParam, FALSE);
    01313
    01314         //
    01315         // Make sure the window didn't get nuked during WM_INITDIALOG
    01316         //
    01317         if (!RevalidateHwnd(hwnd)) {
    01318             goto CreateDialogReturn;
    01319         }
    01320         if (fSuccess && !PDLG(pwnd)->fEnd) {
    01321
    01322             //
    01323             // To remove the two-default-push-buttons problem, we must make
    01324             // sure CheckDefPushButton() will remove default from other push
    01325             // buttons.  This happens only if hwndEditFirst != hwndNewFocus;
    01326             // So, we make it NULL here. This breaks Designer's install
    01327             // program(which can't take a DM_GETDEFID.  So, we do a version
    01328             // check here.
    01329             //
    01330             if (!TestWF(pwnd, DFCONTROL)) {
    01331                 PWND pwndT;
    01332                 if (!IsWindow(hwndEditFirst) || TestWF(pwnd, WFWIN40COMPAT))
    01333                     hwndEditFirst = NULL;
    01334
    01335                 //
    01336                 // They could have disabled hwndEditFirst during WM_INITDIALOG.
    01337                 // So, let use obtain the First Tab again.
    01338                 //
    01339                 pwndT = _GetNextDlgTabItem(pwnd, NULL, FALSE);
    01340                 if (hwndNewFocus = HW(pwndT)) {
    01341                     DlgSetFocus(hwndNewFocus);
    01342                 }
    01343
    01344                 xxxCheckDefPushButton(pwnd, hwndEditFirst, hwndNewFocus);
    01345             }
    01346         }
    01347     }
    01348
    01349     if (!IsWindow(hwnd))
    01350     {
    01351         // Omnis7 relies on a nonzero return even though they nuked this
    01352         // dialog during processing of the WM_INITDIALOG message
    01353         // -- jeffbog -- 2/24/95 -- Win95B B#12368
    01354         if (GETAPPVER() < VER40) {
    01355             return(hwnd);
    01356         }
    01357
    01358         return(NULL);
    01359     }
    01360
    01361     /*
    01362      * UISTATE: if keyboard indicators are on and this is a topmost dialog
    01363      * set the internal bit.
    01364      */
    01365     if (TEST_KbdCuesPUSIF) {
    01366         /*
    01367          * If property page, UISTATE bits were copied from parent when I was created
    01368          * Top level dialogs act as containers and initialize their state based on
    01369          * the type of the last input event, after sending UIS_INITIALIZE
    01370          */
    01371         if (!TestwndChild(pwnd)) {
    01372             SendMessageWorker(pwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_INITIALIZE, 0), 0, FALSE);
    01373         }
    01374     }
    01375
    01376     /*
    01377      * Bring this dialog into the foreground
    01378      * if DS_SETFOREGROUND is set.
    01379      */
    01380     if (bFlags & CD_SETFOREGROUND) {
    01381         NtUserSetForegroundWindow(hwnd);
    01382         if (!IsWindow(hwnd)) {
    01383             hwnd = NULL;
    01384             goto CreateDialogReturn;
    01385         }
    01386     }
    01387
    01388     if ((bFlags & CD_VISIBLE) && !PDLG(pwnd)->fEnd && (!TestWF(pwnd, WFVISIBLE))) {
    01389         NtUserShowWindow(hwnd, SHOW_OPENWINDOW);
    01390         UpdateWindow(hwnd);
    01391     }
    01392
    01393 CreateDialogReturn:
    01394
    01395     /*
    01396      * 17609 Gupta's SQLWin deletes the window before CreateDialog returns
    01397      * but still expects non-zero return value from CreateDialog so we will
    01398      * do like win 3.1 and not revalidate for 16 bit apps
    01399      */
    01400     if (!(fSCDLGFlags & SCDLG_NOREVALIDATE) && !RevalidateHwnd(hwnd)) {
    01401         hwnd = NULL;
    01402     }
    01403
    01404     return hwnd;
    01405 }