home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / fegrid.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  81.8 KB  |  2,804 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19.  
  20. #include "stdafx.h"
  21. #include "gridedge.h"
  22. #include "netsvw.h"
  23. #include "template.h"
  24.  
  25. #define VIEW_SOURCE_TARGET_WINDOW_NAME "%ViewSourceWindow"    /* from ns/lib/libnet/cvcolor.c */
  26.  
  27. MWContext *FE_MakeGridWindow(MWContext *pOldContext, void *hist_list, void *pHistory,
  28.     int32 lX, int32 lY,
  29.     int32 lWidth, int32 lHeight, char *pUrlStr, char *pWindowName, int8 iScrollType,
  30.     NET_ReloadMethod eReloadThis, Bool no_edge)    {
  31.  
  32.     //    First, ensure that the context we're going into is of an appropriate type.
  33.     if(pOldContext == NULL || ABSTRACTCX(pOldContext)->IsFrameContext() == FALSE)    {
  34.         //    Only let this happen to window contexts for now.
  35.         return(NULL);
  36.     }
  37.     else    {
  38.         //    The goal here is to create a new, fabulous, grid that is a child of the
  39.         //        other window context's frame.
  40.         CWinCX *pParentCX = VOID2CX(pOldContext->fe.cx, CWinCX);
  41.  
  42.         //    Safety dance.
  43.         if(pParentCX->GetPane() == NULL)    {
  44.             return(NULL);
  45.         }
  46.  
  47.         HWND hParentWnd = pParentCX->GetPane();
  48.  
  49.         //    Bring up a create context, so that the Create call won't complain on
  50.         //        16 bit windows.
  51.         //    Since we create the context here, and the document, along with the view,
  52.         //        the view takes care of destroying the docuemnt on close, so we don't
  53.         //        need to worry about it.
  54.         CCreateContext cccGrid;
  55.         cccGrid.m_pNewViewClass = RUNTIME_CLASS(CNetscapeView);
  56.         cccGrid.m_pCurrentDoc = new CGenericDoc();
  57.  
  58.         //    Create the view.
  59.         DWORD dwGridStyle = WS_HSCROLL | WS_VSCROLL;
  60.         CNetscapeView *pNewView = new CNetscapeView();
  61.         pNewView->Create(NULL,
  62.                pWindowName,
  63.                dwGridStyle,
  64.             CRect(0, 0, 1, 1),
  65.             CWnd::FromHandle(hParentWnd),
  66.             0,
  67.             &cccGrid);
  68.  
  69.         CWinCX *pWinCX = new CWinCX((CGenericDoc *)cccGrid.m_pCurrentDoc, pParentCX->GetFrame(), pNewView);
  70.  
  71.         //    Set the context's name.
  72.         //    Set its parent.
  73.         pWinCX->SetContextName(pWindowName);
  74.         pWinCX->SetParentContext(pOldContext);
  75.  
  76.         RECT rect;
  77.         rect.left = CASTINT(pParentCX->Twips2PixX(lX));
  78.         rect.top = CASTINT(pParentCX->Twips2PixY(lY));
  79.         rect.right = CASTINT(pParentCX->Twips2PixX(lX) + pParentCX->Twips2PixX(lWidth));
  80.         rect.bottom = CASTINT(pParentCX->Twips2PixY(lY) + pParentCX->Twips2PixY(lHeight));
  81.         //    Initialize the context.
  82.         pWinCX->Initialize(pWinCX->CDCCX::IsOwnDC(), &rect);
  83.  
  84.         //  Tell it wether or not it will have an edge (border in the
  85.         //      non client area).
  86.         pWinCX->SetBorder(!no_edge);
  87.  
  88.         //  Size the window to final coords.
  89.         //  This causes the non client calc to happen which is needed
  90.         //      now that it knows it's a grid cell.
  91.         pNewView->MoveWindow(
  92.             CRect(CASTINT(pParentCX->Twips2PixX(lX)),
  93.                CASTINT(pParentCX->Twips2PixY(lY)),
  94.                CASTINT(pParentCX->Twips2PixX(lX) + pParentCX->Twips2PixX(lWidth)),
  95.                CASTINT(pParentCX->Twips2PixY(lY) + pParentCX->Twips2PixY(lHeight))),
  96.             FALSE);
  97.  
  98.         //    Decide what we're doing about scroll bars.
  99.         switch(iScrollType)    {
  100.         case LO_SCROLL_NO:
  101.             //    Shouldn't ever have scrollbars.
  102.             //    Get rid of them.
  103.             pWinCX->SetDynamicScrollBars(FALSE);
  104.             pWinCX->ShowScrollBars(SB_BOTH, FALSE);
  105.             pWinCX->SetAlwaysShowScrollBars(FALSE);
  106.             break;
  107.         case LO_SCROLL_AUTO:
  108.             //    Aha, the hard case.
  109.             //    Set a flag so that when the load is complete in the context, such
  110.             //        that we will hide the scroll bars if there is already enough room.
  111.             //    This means that the entire document fits on the screen (not much data),
  112.             //        and that doing a load from resize at that point will be minimal
  113.             //        overhead.
  114.             pWinCX->SetDynamicScrollBars(TRUE);
  115.             pWinCX->SetAlwaysShowScrollBars(FALSE);
  116.             break;
  117.         case LO_SCROLL_YES:
  118.             //    Have the scroll bars show.
  119.             pWinCX->SetDynamicScrollBars(FALSE);
  120.             pWinCX->SetAlwaysShowScrollBars(TRUE);
  121.             pWinCX->ShowScrollBars(SB_BOTH, TRUE);
  122.             break;
  123.         default:
  124.             ASSERT(0);    // user mush pass in invalid value.
  125.         }
  126.  
  127.         //    If we have a history list, we need to stick it in the context.
  128.         History_entry *pHistEnt = (History_entry *)pHistory;
  129.         XP_List *pHistList = (XP_List *)hist_list;
  130.         if(pHistList != NULL)    {
  131.             pWinCX->GetContext()->hist.list_ptr = pHistList;
  132.         }
  133.         else    {
  134.             //    If we have a history entry, we need to add it to the session.
  135.             if(pHistEnt != NULL)    {
  136.                 SHIST_AddDocument(pWinCX->GetContext(), pHistEnt);
  137.             }
  138.         }
  139.  
  140.         //    Have it load the url in question.
  141.         //    This could be from the history entry.
  142.         if(pHistEnt == NULL)    {
  143.             URL_Struct *pUrl = NET_CreateURLStruct(pUrlStr, NET_DONT_RELOAD);
  144.             pUrl->force_reload = eReloadThis;
  145.  
  146.             //  Be sure to add the referrer field of the top level context.
  147.             MWContext *mwRefer = pOldContext;
  148.             while(mwRefer->grid_parent) {
  149.                 mwRefer = mwRefer->grid_parent;
  150.             }
  151.             History_entry *he = SHIST_GetCurrent (&mwRefer->hist);
  152.             if(he && he->referer)   {
  153.                 pUrl->referer = XP_STRDUP(he->referer);
  154.             }
  155.  
  156.             pWinCX->GetUrl(pUrl, FO_CACHE_AND_PRESENT);
  157.         }
  158.         else    {
  159.             URL_Struct *pUrl = SHIST_CreateURLStructFromHistoryEntry(pWinCX->GetContext(), pHistEnt);
  160.             pUrl->force_reload = eReloadThis;
  161.             pWinCX->GetUrl(pUrl, FO_CACHE_AND_PRESENT);
  162.         }
  163.  
  164.         // Grid parents have WS_CLIPCHILDREN turned on. This allows them
  165.         // to draw (backgrounds for example) into their windows without
  166.         // worrying about their children.
  167.         CFrameGlue *pGlue = pWinCX->GetFrame();
  168.         if(pGlue) {
  169.             pGlue->ClipChildren(pNewView, TRUE);
  170.         }
  171.  
  172.         //    Show the window, but don't activate it.
  173.         pNewView->ShowWindow(SW_SHOWNA);
  174.  
  175.         return(pWinCX->GetContext());
  176.     }
  177. }
  178.  
  179. void FE_LoadGridCellFromHistory(MWContext *pContext, void *hist, NET_ReloadMethod netReloadMethod) {
  180.     History_entry *pHist = (History_entry *)hist;
  181.  
  182.     if (pHist != NULL)    {
  183.         URL_Struct *pUrl = SHIST_CreateURLStructFromHistoryEntry(pContext, pHist);
  184.         if(pUrl)    {
  185.             pUrl->force_reload = netReloadMethod;
  186.             ABSTRACTCX(pContext)->GetUrl(pUrl, FO_CACHE_AND_PRESENT, TRUE);
  187.         }
  188.     }
  189. }
  190.  
  191. void *FE_FreeGridWindow(MWContext *pContext, XP_Bool bSaveHistory)    {
  192.     ASSERT(ABSTRACTCX(pContext)->IsWindowContext());
  193.  
  194.     void *pRetval = NULL;
  195.  
  196.     //    Destroy the view then the doc/it in turn destroys the context.
  197.     //    We have to clean up the doc, since we passed it in....
  198.     CWinCX *pWinCX = VOID2CX(pContext->fe.cx, CWinCX);
  199.     CWinCX *pParentCX =  WINCX(pWinCX->GetParentContext());
  200.  
  201.     //    We may want to return the history entry.
  202.     if(bSaveHistory == TRUE)    {
  203.         //  Reset to top of document
  204.            SHIST_SetPositionOfCurrentDoc(&(pWinCX->GetContext()->hist), 0);
  205.         if(pWinCX->GetOriginX() || pWinCX->GetOriginY())    {
  206. #ifdef LAYERS
  207.             LO_Any *pAny = (LO_Any *)LO_XYToNearestElement(pWinCX->GetContext(), pWinCX->GetOriginX(), pWinCX->GetOriginY(), NULL);
  208. #else
  209.             LO_Any *pAny = (LO_Any *)LO_XYToNearestElement(pWinCX->GetContext(), pWinCX->GetOriginX(), pWinCX->GetOriginY());
  210. #endif
  211.  
  212.             //    Save the location of the current document.
  213.             if(pAny != NULL)    {
  214.                 SHIST_SetPositionOfCurrentDoc(&(pWinCX->GetContext()->hist), pAny->ele_id);
  215.             }
  216.         }
  217.  
  218.         LO_DiscardDocument(pWinCX->GetContext());
  219.         XP_List *hist_list = pWinCX->GetContext()->hist.list_ptr;
  220.         pWinCX->GetContext()->hist.list_ptr = NULL;
  221.  
  222.         pRetval = (void *)hist_list;
  223.     }
  224.  
  225.     CFrameGlue *frame = pWinCX->GetFrame();
  226.  
  227.     //  Make sure child grid cell going away doesn't hold onto frame
  228.     //    which may also be going down.
  229.     pWinCX->ClearFrame();
  230.  
  231.     ASSERT(pWinCX->GetPane());
  232.     if(pWinCX->GetPane())    {
  233.         CGenericView *pView = pWinCX->GetView();
  234.  
  235.         ASSERT(pView);
  236.         if(pView)   {
  237.             // Tell our parent(s) that they don't need to clip children
  238.             // anymore just for our sake.
  239.             if(frame) {
  240.                 frame->ClipChildren(pView, FALSE);
  241.             }
  242.             pView->FrameClosing();
  243.             pView->SendMessage(WM_CLOSE);
  244.         }
  245.     }
  246.  
  247.     return(pRetval);
  248. }
  249.  
  250. void FE_GetFullWindowSize(MWContext *pContext, int32 *plWidth, int32 *plHeight)    {
  251.  
  252.     //    Only do this on windows.
  253.     if(ABSTRACTCX(pContext)->IsWindowContext() == TRUE && ABSTRACTCX(pContext)->IsDestroyed() == FALSE)    {
  254.         CPaneCX *pWindow = PANECX(pContext);
  255.  
  256.         RECT crDimensions;
  257.  
  258.         //    Get the full size of the window.
  259.         ::GetClientRect(pWindow->GetPane(), &crDimensions);
  260.  
  261.         //    Convert the dimensions to twips.
  262.         HDC hDC = pWindow->GetContextDC();
  263.         ::DPtoLP(hDC, (POINT *)&crDimensions, 2);
  264.         pWindow->ReleaseContextDC(hDC);
  265.  
  266.         *plWidth = crDimensions.right - crDimensions.left;
  267.         *plHeight = crDimensions.bottom - crDimensions.top;
  268.         
  269.         //  Adjust to not include scroll bars.
  270.         if(pWindow->IsVScrollBarOn()) {
  271.             *plWidth += sysInfo.m_iScrollWidth;
  272.         }
  273.         if(pWindow->IsHScrollBarOn()) {
  274.             *plHeight += sysInfo.m_iScrollHeight;
  275.         }
  276.     }
  277.     else    {
  278.         //    No window here....
  279.         //  Set to 1 to avoid divide by zero errors in Back end.
  280.         *plHeight = *plWidth = 1;
  281.     }
  282. }
  283.  
  284. void FE_RestructureGridWindow(MWContext *pContext, int32 lX, int32 lY, int32 lWidth, int32 lHeight)    {
  285.     TRACE("FE_RestructureGridWindow(%p, %ld, %ld, %ld, %ld)\n", pContext, lX, lY, lWidth, lHeight);
  286.  
  287.     //    Safety dance.
  288.     if(pContext == NULL)    {
  289.         return;
  290.     }
  291.  
  292.     //    We're under the immediate assumption that the context is a window.
  293.     ASSERT(ABSTRACTCX(pContext)->IsWindowContext());
  294.  
  295.     CWinCX *pWinCX = WINCX(pContext);
  296.  
  297.     //    We need to move the window.
  298.     //    It will automagically redraw itself.
  299.     ::MoveWindow(pWinCX->GetPane(), CASTINT(pWinCX->Twips2PixX(lX)),
  300.         CASTINT(pWinCX->Twips2PixY(lY)),
  301.         CASTINT(pWinCX->Twips2PixX(lWidth)),
  302.         CASTINT(pWinCX->Twips2PixY(lHeight)),
  303.         TRUE);
  304.  
  305.     //    Dynamic scroll bars are handled internally, as is resize.
  306. }
  307.  
  308. void FE_SetWindowLoading(MWContext *pContext, URL_Struct *pUrl, Net_GetUrlExitFunc **ppExitRoutine)    {
  309.  
  310.     //    A url load is changing context.
  311.     //    Telling the exit routine that we'd like to be called.
  312.     *ppExitRoutine = CFE_GetUrlExitRoutine;
  313.  
  314.     //    Now, call the GetUrl routine, but don't really load.
  315.     //    This bootstraps the normal loading procedure.
  316.     //    DON'T REALLY CARE WHAT WE PASS IN AS THE PRESENTATION TYPE, yet.
  317.     ABSTRACTCX(pContext)->GetUrl(pUrl, FO_CACHE_AND_PRESENT, FALSE);
  318. }
  319.  
  320. void FE_GetEdgeMinSize(MWContext *pContext, int32 *pSize, Bool no_edge)    {
  321.     TRACE("FE_GetEdgeMinSize(%p, %p)\n", pContext, pSize);
  322.  
  323.     //  Don't care anymore.
  324.     *pSize = 5;
  325.  
  326.     if(!no_edge)    {
  327.         *pSize = 5;
  328.     }
  329. }
  330.  
  331. MWContext *FE_MakeBlankWindow(MWContext *pOldContext, URL_Struct *pUrl, char *pContextName)    {
  332. //    TRACE("FE_MakeBlankWindow(%p, %p, %s)\n", pOldContext, pUrl, pContextName);
  333.  
  334.     //    Create a new top level blank window.
  335.     //    Only don't load anything.  Leave it blank.
  336.     //    HACK ALERT:
  337.     //    In order to better do this, we need to have the CreateNewDocWindow
  338.     //        function not load what's in the history.  It only does this with
  339.     //        other browser windows.  Anyhow, switch our context type temporarily
  340.     //        in order to get the effect.
  341.     MWContextType OldType = pOldContext->type;
  342.     pOldContext->type = (MWContextType)-1;
  343.     MWContext *pRetval = pOldContext->funcs->CreateNewDocWindow(pOldContext, NULL);
  344.     pOldContext->type = OldType;
  345.  
  346.     if(pRetval != NULL)    {
  347.         ABSTRACTCX(pRetval)->SetContextName(pContextName);
  348.     }
  349.  
  350.     return(pRetval);
  351. }
  352.  
  353. //    Create a new window.
  354. //    If pChrome is NULL, do a FE_MakeBlankWindow....
  355. //    pChrome specifies the attributes of a window.
  356. //  If you use this call, Toolbar information will not be saved in the preferences.
  357. MWContext *FE_MakeNewWindow(MWContext *pOldContext, URL_Struct *pUrl, char *pContextName, Chrome *pChrome)
  358. {
  359.  
  360.     BOOL bNetHelpWnd = FALSE;
  361.     
  362.     
  363.     //    Decide which type of context this will be (we use this to possible access some templates).
  364.     MWContextType cxType = MWContextAny;
  365.     if(pChrome != NULL)    {
  366.         switch(pChrome->type)    {
  367.             case MWContextHTMLHelp:
  368.                 pChrome->type = MWContextBrowser;
  369.               #ifndef _WIN32
  370.                 pChrome->allow_resize = FALSE;
  371.               #endif  
  372.                 bNetHelpWnd = TRUE;
  373.                 // Fall through...
  374.             case MWContextBrowser:
  375.                 cxType = MWContextBrowser;
  376.                 break;
  377.             case MWContextDialog:
  378.                 cxType = MWContextDialog;
  379.                 break;
  380.         }
  381.     }
  382.     else    {
  383.         //    Default to MWContextBrowser;
  384.         cxType = MWContextBrowser;
  385.     }
  386.  
  387.     //    A type came in that we're not ready to handle.
  388.     //    Seems more code needs to be written....
  389.     ASSERT(cxType != MWContextAny);
  390.     if(cxType == MWContextAny)    {
  391.         return(NULL);
  392.     }
  393.  
  394.     //  Decide now wether or not to make the window initially visible.
  395.     //  We decide by detecting wether or not we'll be enforcing a resize.
  396.     //  We'll make the window visible after we're done sizing.
  397.     //  Only works with 32 bits right now.
  398.     BOOL bMakeVisible = TRUE;
  399.     if(pChrome && ((pChrome->outw_hint && pChrome->outh_hint) || 
  400.         (pChrome->w_hint && pChrome->h_hint)   ||
  401.         pChrome->location_is_chrome ||
  402.         pChrome->topmost || pChrome->bottommost)) {
  403.         bMakeVisible = FALSE;
  404.     }
  405.  
  406.     //  Must check if user wants a titlebar now since it affects the type of 
  407.     //  window used during window creation.  If no titlebar, use popup type.
  408.     BOOL bHideTitlebar = FALSE;
  409.     BOOL bBorder = TRUE;
  410.     if (pChrome && pChrome->hide_title_bar){
  411.         bHideTitlebar = TRUE;
  412.     }
  413.  
  414.     BOOL bDependent = FALSE;
  415.     if (pOldContext && pChrome && pChrome->dependent) {    
  416.         bDependent = TRUE;
  417.     }
  418.  
  419.     //    Take the template of the appropriate window type, and pull it up.
  420.     CAbstractCX *pCX = NULL;
  421.  
  422.     // If there is a parent, get its hwnd
  423.     CWinCX *pOldWinCX = NULL;
  424.     if(pOldContext)
  425.         pOldWinCX = WINCX(pOldContext);
  426.  
  427.     HWND    hParentHwnd = NULL;
  428.     if(pOldWinCX && pOldWinCX->GetFrame() && pOldWinCX->GetFrame()->GetFrameWnd())
  429.         hParentHwnd = pOldWinCX->GetFrame()->GetFrameWnd()->GetSafeHwnd();
  430.  
  431.  
  432.     switch(cxType)    {
  433.         case MWContextBrowser:
  434.         case MWContextDialog:    {
  435.             BOOL bPopup = FALSE;
  436.             HWND hPopupParent = NULL;
  437.  
  438.             // if we are creating a modal window then we need to become a child of
  439.             // the calling frame and of type WS_POPUP.  The values below are set to
  440.             // tell the frame to create itself this way.
  441.             if(hParentHwnd && pChrome && pChrome->is_modal)
  442.             {
  443.                 bPopup = TRUE;
  444.                 hPopupParent = ::GetLastActivePopup(hParentHwnd);
  445.             }
  446.  
  447.             CGenericDoc *pDoc = 
  448.                 (CGenericDoc *)theApp.m_ViewTmplate->OpenDocumentFile(NULL, bMakeVisible, 
  449.                                     bHideTitlebar, bDependent, bPopup, hPopupParent);
  450.                 if(pDoc != NULL)    {
  451.                     pCX = pDoc->GetContext();
  452.                 }
  453.             }
  454.  
  455.             
  456.             break;
  457.         default:
  458.             //    Please add your case statement.
  459.             ASSERT(0);
  460.             break;
  461.     }
  462.  
  463.     //    If the context wasn't created, we can not continue.
  464.     if(pCX == NULL)    {
  465.         return(NULL);
  466.     }
  467.  
  468.     // Hack to identify a NetHelp window
  469.     pCX->m_bNetHelpWnd = bNetHelpWnd;
  470.     
  471.     // JavaScript can create windows which are lifetime-linked to their parent.
  472.     // This is set here instead of in JS to avoid threading problems. 
  473.     
  474.     if (bDependent) {    
  475.         if (pOldContext->js_dependent_list == NULL)
  476.             pOldContext->js_dependent_list = XP_ListNew();
  477.         if (pOldContext->js_dependent_list == NULL)
  478.             return(NULL);
  479.         XP_ListAddObject(pOldContext->js_dependent_list, pCX->GetContext());
  480.         pCX->GetContext()->js_parent = pOldContext;
  481.     }
  482.  
  483.  
  484.     //    Get the context, and manually assign its type.
  485.     //    The XP context that is.
  486.     pCX->GetContext()->type = cxType;
  487.  
  488.     //    Assign the context name, if provided.
  489.     if(pContextName != NULL)    {
  490.         pCX->SetContextName(pContextName);
  491.     }
  492.  
  493.     //    Copy over the same char set ID as the old context if we're a window.
  494.     if(pCX->IsFrameContext() == TRUE && pOldContext != NULL)    {
  495.         CWinCX *pWinCX = VOID2CX(pCX, CWinCX);
  496.         if(cxType != MWContextDialog && !bNetHelpWnd) {
  497.             pWinCX->GetFrame()->m_iCSID = INTL_DefaultDocCharSetID(pOldContext);
  498.         } else {
  499.             // use the client's default encoding for HTML dialogs (fix for #78838)
  500.             pWinCX->GetFrame()->m_iCSID = INTL_CharSetNameToID(INTL_ResourceCharSet());
  501.             if (pContextName != NULL) {
  502.                 if(strncmp(pContextName, VIEW_SOURCE_TARGET_WINDOW_NAME,
  503.                     strlen(VIEW_SOURCE_TARGET_WINDOW_NAME)) == 0)    {
  504.                     // but not for View Source which gets the old context char set ID 
  505.                     // (fix for #79072)
  506.                     pWinCX->GetFrame()->m_iCSID = INTL_DefaultDocCharSetID(pOldContext);
  507.                 }
  508.                 if(strncmp(pContextName, "%DocInfoWindow", 14) == 0)    {
  509.                     // %DocInfoWindow is from ns/lib/libnet/mkgeturl.c net_output_about_url()
  510.                     // Document Info gets the user-selectable default encoding
  511.                     pWinCX->GetFrame()->m_iCSID = INTL_DefaultWinCharSetID(NULL);
  512.                 }
  513.             }
  514.         }
  515.     }
  516.  
  517.   #ifdef _WIN32
  518.     if(sysInfo.m_bWin4 && bNetHelpWnd && pCX->IsFrameContext()) {
  519.     
  520.         CWinCX *pWinCX = VOID2CX(pCX, CWinCX);
  521.         CFrameWnd *pFrame = pWinCX->GetFrame()->GetFrameWnd();
  522.     
  523.         if( pFrame ) {
  524.                HICON hIcon = theApp.LoadIcon( "IDR_NETHELP_ICON" );
  525.                pFrame->SetIcon( hIcon, TRUE );
  526.  
  527.                hIcon = (HICON)::LoadImage( AfxFindResourceHandle( "IDR_NETHELP_ICON", RT_GROUP_ICON ), "IDR_NETHELP_ICON", IMAGE_ICON,
  528.                                         GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ), LR_SHARED );
  529.                pFrame->SetIcon( hIcon, FALSE );
  530.         }
  531.     }
  532.    #endif // _WIN32
  533.        
  534.     //    Pay special attention to the chrome attributes specified, if specified.
  535.     //    If they aren't, attempt to use attributes from the old context passed in.
  536.     if(pChrome != NULL && pCX->IsFrameContext() == TRUE)    {
  537.         CWinCX *pWinCX = VOID2CX(pCX, CWinCX);
  538.         
  539.         LPCHROME pIChrome = pWinCX->GetFrame()->GetChrome();
  540.         if(pIChrome) {
  541.             //    Url bar and directory buttons.
  542.             // make it so that we don't save toolbar information
  543.             pIChrome->SetSaveToolbarInfo(FALSE);
  544.             pIChrome->ShowToolbar(ID_LOCATION_TOOLBAR, pChrome->show_url_bar);
  545.             pIChrome->ShowToolbar(ID_PERSONAL_TOOLBAR, pChrome->show_directory_buttons);
  546.             pIChrome->ShowToolbar(ID_NAVIGATION_TOOLBAR, pChrome->show_button_bar);
  547.  
  548.             //    Status bar!
  549.             LPNSSTATUSBAR pIStatusBar = NULL;
  550.             pIChrome->QueryInterface( IID_INSStatusBar, (LPVOID *) &pIStatusBar );
  551.             if ( pIStatusBar ) {
  552.                 pIStatusBar->Show( pChrome->show_bottom_status_bar );
  553.                 pIStatusBar->Release();
  554.             }
  555.         }
  556.  
  557.         //    Show the menu?
  558.         if(pChrome->show_menu == FALSE)    {
  559.             CMenu *pMenu = pWinCX->GetFrame()->GetFrameWnd()->GetMenu();
  560.             HMENU hMenu = pMenu ? pMenu->m_hMenu : NULL;                    
  561.             pWinCX->GetFrame()->GetFrameWnd()->SetMenu(NULL);
  562.             if( hMenu && (theApp.m_ViewTmplate->m_hMenuShared != hMenu) )
  563.             {
  564.                 pMenu->DestroyMenu();
  565.             }
  566.         }
  567.  
  568.         //    Need to recalc.
  569.         pWinCX->GetFrame()->GetFrameWnd()->RecalcLayout();
  570.  
  571.         //    Size, of all things, of the viewing area only....
  572.         //    Doesn't account for menu wrap or unwrap when getting smaller/bigger.
  573.         if((pChrome->outw_hint && pChrome->outh_hint) || 
  574.             (pChrome->w_hint &&pChrome->h_hint)   ||
  575.             pChrome->location_is_chrome ||
  576.             pChrome->topmost || pChrome->bottommost) {
  577.  
  578.             int32 lLeft=0;
  579.             int32 lTop=0;
  580.             int32 lWidth=0;
  581.             int32 lHeight=0;
  582.  
  583.             CRect crFrame;
  584.             pWinCX->GetFrame()->GetFrameWnd()->GetWindowRect(crFrame);
  585.             CRect crView;
  586.             ::GetWindowRect(pWinCX->GetPane(), crView);
  587.             
  588.             //    Acount for the view border style.
  589.             crView.InflateRect(-1 * sysInfo.m_iBorderWidth, -1 * sysInfo.m_iBorderHeight);
  590.  
  591.             int32 lWAdjust = pChrome->w_hint - (int32)crView.Width();
  592.             int32 lHAdjust = pChrome->h_hint - (int32)crView.Height();
  593.  
  594.             if (pChrome->outw_hint>0 && pChrome->outh_hint>0) {
  595.                 lWidth = pChrome->outw_hint;
  596.                 lHeight = pChrome->outh_hint;
  597.             }
  598.             else if (pChrome->w_hint>0 && pChrome->h_hint>0) {
  599.                 lWidth = (int32)crFrame.Width() + lWAdjust;
  600.                 lHeight = (int32)crFrame.Height() + lHAdjust;
  601.             }
  602.             else {
  603.                 lWidth = (int32)crFrame.Width();
  604.                 lHeight = (int32)crFrame.Height();
  605.             }
  606.  
  607.             if (pChrome->location_is_chrome) {
  608.                 lLeft = pChrome->l_hint;
  609.                 lTop = pChrome->t_hint;
  610.             }
  611.             else {
  612.                 lLeft = (int32)crFrame.left;
  613.                 lTop = (int32)crFrame.top;
  614.             }
  615.   
  616.             //There is a security problem where the window size buffer can be 
  617.             //overridden on Win95.  Using arbitrary max window size of 10000
  618.             lWidth = lWidth > 10000 ? 10000 : lWidth;
  619.             lHeight = lHeight > 10000 ? 10000 : lHeight;
  620.  
  621.             if (pChrome->topmost)
  622.                 pWinCX->GetFrame()->GetFrameWnd()->SetWindowPos(&CWnd::wndTopMost, CASTINT(lLeft), CASTINT(lTop), CASTINT(lWidth), CASTINT(lHeight), NULL);
  623.             else if (pChrome->bottommost)
  624.                 pWinCX->GetFrame()->GetFrameWnd()->SetWindowPos(&CWnd::wndBottom, CASTINT(lLeft), CASTINT(lTop), CASTINT(lWidth), CASTINT(lHeight), NULL);
  625.             else
  626.                 pWinCX->GetFrame()->GetFrameWnd()->MoveWindow(CASTINT(lLeft), CASTINT(lTop), CASTINT(lWidth), CASTINT(lHeight));
  627.  
  628.         //  Specific width and height information means that we should not save the sizes when closing down, regardless of context type.
  629.         pWinCX->m_bSizeIsChrome = TRUE;
  630.         }
  631.  
  632.         //    Set windows always on bottom.
  633.         pWinCX->SetZOrder(pChrome->z_lock, pChrome->bottommost);
  634.  
  635.         //    Modality.
  636.         if(pChrome->is_modal)    {
  637.             //    Inform the context of its special status.
  638.             pWinCX->GoModal(pOldContext);
  639.         }
  640.  
  641.         //    Scroll bars.
  642.         if(pChrome->show_scrollbar == FALSE)    {
  643.             //    Turn them off.
  644.             pWinCX->SetDynamicScrollBars(FALSE);
  645.             pWinCX->ShowScrollBars(SB_BOTH, FALSE);
  646.             pWinCX->SetAlwaysShowScrollBars(FALSE);
  647.         }
  648.  
  649.         //    Resize.
  650.         if(pChrome->allow_resize == FALSE)    {
  651.             //    Disable resize....
  652.             //    This is a truly gross and unholy option.
  653.             pWinCX->EnableResize(FALSE);
  654.         }
  655.  
  656.         //    Hotkeys
  657.         if (pChrome->disable_commands) {    
  658.             //    Disable hotkeys
  659.             
  660.             pWinCX->DisableHotkeys(TRUE);
  661.         }
  662.  
  663.         //    Close.
  664.         if(pChrome->allow_close == FALSE)    {
  665.             //    Disable closing....
  666.             //    This is a truly gross and unholy option.
  667.             //    This is reenabled in FE_DestroyContext regardless (i.e.
  668.             //        can't be closed unless someone calls that API).
  669.             pWinCX->EnableClose(FALSE);
  670.         }
  671.  
  672.         //    Don't allow restricted target windows to be targeted
  673.         //    by mail links and other functions which just grab 
  674.         //    the nearest Browser context.
  675.         if(pChrome->restricted_target)
  676.             pCX->GetContext()->restricted_target = TRUE;
  677.  
  678.         //    Close callback.
  679.         //    Callback when the context is destroyed.
  680.         pWinCX->CloseCallback(pChrome->close_callback, pChrome->close_arg);
  681.  
  682.         //    History copy.
  683.         if(pChrome->copy_history && pOldContext != NULL)    {
  684.             //    Copy the old context's history.
  685.             SHIST_CopySession(pWinCX->GetContext(), pOldContext);
  686.         }
  687.     }
  688.     else if(cxType == MWContextBrowser && pCX->IsFrameContext() == TRUE)    {
  689.         CWinCX *pWinCX = VOID2CX(pCX, CWinCX);
  690.  
  691.         //    See if the calling context is a window context, and if so, emulate its
  692.         //        settings.
  693.         //    Otherwise, just take what we have up....
  694.         if(pOldContext != NULL && pOldContext->type == MWContextBrowser)    {
  695.             CWinCX *pOldCX = WINCX(pOldContext);
  696.  
  697.             LPCHROME pIChrome = pWinCX->GetFrame()->GetChrome();
  698.             if(pIChrome) {
  699.                 // Directory buttons, location box and all
  700.                 // make it so that we don't save toolbar information
  701.                 pIChrome->SetSaveToolbarInfo(FALSE);
  702.                 pIChrome->SetToolbarStyle( theApp.m_pToolbarStyle );
  703.  
  704.                 pIChrome->ShowToolbar( ID_LOCATION_TOOLBAR, pOldCX->GetFrame()->m_bLocationBar );
  705.                 pIChrome->ShowToolbar(ID_PERSONAL_TOOLBAR, pOldCX->GetFrame()->m_bStarter);
  706.                 pIChrome->ShowToolbar(ID_NAVIGATION_TOOLBAR, pOldCX->GetFrame()->m_bShowToolbar);
  707.             }
  708.         }
  709.     }
  710.  
  711.     //    If a URL struct was passed in, load it as the last thing to do.
  712.     if(pUrl != NULL)    {
  713.         int iFormatOut = FO_CACHE_AND_PRESENT;
  714.         switch(cxType)    {
  715.             case MWContextBrowser:
  716.             case MWContextDialog:
  717.                 iFormatOut = FO_CACHE_AND_PRESENT;
  718.                 break;
  719.             default:
  720.                 //    May be a different format out depending on context type.
  721.                 //    Please set as appropriate!
  722.                 ASSERT(0);
  723.                 break;
  724.         }
  725.         pCX->GetUrl(pUrl, iFormatOut);
  726.     }
  727.  
  728.     //  If we hid the window earlier due to sizing information, time to make it come back.
  729.     if(pCX->IsFrameContext() == TRUE && !bMakeVisible)    {
  730.         VOID2CX(pCX, CWinCX)->GetFrame()->GetFrameWnd()->ShowWindow(SW_SHOW);
  731.     }
  732.     
  733.     //    Return the XP context.
  734.     return(pCX->GetContext());
  735. }
  736.  
  737. //  Update current chrome in a context.
  738. void FE_UpdateChrome(MWContext *pContext, Chrome *pChrome)
  739. {
  740.     TRACE("FE_UpdateChrome(%p, %p)\n", pContext, pChrome);
  741.  
  742.     //  API fulfillments.
  743.     if(!pContext || !pChrome || !ABSTRACTCX(pContext) || !ABSTRACTCX(pContext)->IsFrameContext())   {
  744.         return;
  745.     }
  746.  
  747.     CWinCX *pWinCX = WINCX(pContext);
  748.     if(!pWinCX->GetPane() || !pWinCX->GetFrame() || !pWinCX->GetFrame()->GetFrameWnd())    {
  749.         //  Context isn't anatomically correct.
  750.         return;
  751.     }
  752.  
  753.     LPCHROME pIChrome = pWinCX->GetFrame()->GetChrome();
  754.     if(pIChrome) {
  755.         //    Url bar and directory buttons.
  756.         pIChrome->SetSaveToolbarInfo(FALSE);
  757.         pIChrome->ShowToolbar(ID_LOCATION_TOOLBAR,  pChrome->show_url_bar );
  758.         pIChrome->ShowToolbar(ID_PERSONAL_TOOLBAR,  pChrome->show_directory_buttons );
  759.         pIChrome->ShowToolbar(ID_NAVIGATION_TOOLBAR, pChrome->show_button_bar);
  760.  
  761.         //    Status bar!
  762.         LPNSSTATUSBAR pIStatusBar = NULL;
  763.         pIChrome->QueryInterface( IID_INSStatusBar, (LPVOID *) &pIStatusBar );
  764.         if ( pIStatusBar ) {
  765.             pIStatusBar->Show( pChrome->show_bottom_status_bar );
  766.             pIStatusBar->Release();
  767.         }
  768.     }
  769.  
  770.     //    Show the menu?
  771.     if(pChrome->show_menu == FALSE)    {
  772.         CMenu *pMenu = pWinCX->GetFrame()->GetFrameWnd()->GetMenu();
  773.         HMENU hMenu = pMenu ? pMenu->m_hMenu : NULL;        
  774.          pWinCX->GetFrame()->GetFrameWnd()->SetMenu(NULL);
  775.         if( hMenu && (theApp.m_ViewTmplate->m_hMenuShared != hMenu) )
  776.         {
  777.             pMenu->DestroyMenu();
  778.         }
  779.     }
  780.     else    {                                                            
  781.         //  Get the menu back out of the template.
  782.         CMenu *pMenu = pWinCX->GetFrame()->GetFrameWnd()->GetMenu();
  783.         HMENU hMenu = pMenu ? pMenu->m_hMenu : NULL;
  784.         ::SetMenu(pWinCX->GetFrame()->GetFrameWnd()->GetSafeHwnd(), theApp.m_ViewTmplate->m_hMenuShared);
  785.         if( hMenu && (theApp.m_ViewTmplate->m_hMenuShared != hMenu) )
  786.         {
  787.             pMenu->DestroyMenu();
  788.         }
  789.     }
  790.  
  791.     //    Need to recalc.
  792.     pWinCX->GetFrame()->GetFrameWnd()->RecalcLayout();
  793.  
  794.     //    Size, of all things, of the viewing area only....
  795.     //    Doesn't account for menu wrap or unwrap when getting smaller/bigger.
  796.     if((pChrome->outw_hint && pChrome->outh_hint) || 
  797.         (pChrome->w_hint &&pChrome->h_hint)   ||
  798.         pChrome->location_is_chrome ||
  799.         pChrome->topmost || pChrome->bottommost) {
  800.  
  801.         int32 lLeft=0;
  802.         int32 lTop=0;
  803.         int32 lWidth=0;
  804.         int32 lHeight=0;
  805.  
  806.         CRect crFrame;
  807.         pWinCX->GetFrame()->GetFrameWnd()->GetWindowRect(crFrame);
  808.         CRect crView;
  809.         ::GetWindowRect(pWinCX->GetPane(), crView);
  810.         
  811.         //    Acount for the view border style.
  812.         crView.InflateRect(-1 * sysInfo.m_iBorderWidth, -1 * sysInfo.m_iBorderHeight);
  813.  
  814.         int32 lWAdjust = pChrome->w_hint - (int32)crView.Width();
  815.         int32 lHAdjust = pChrome->h_hint - (int32)crView.Height();
  816.  
  817.         if (pChrome->outw_hint>0 && pChrome->outh_hint>0) {
  818.             lWidth = pChrome->outw_hint;
  819.             lHeight = pChrome->outh_hint;
  820.         }
  821.         else if (pChrome->w_hint>0 && pChrome->h_hint>0) {
  822.             lWidth = (int32)crFrame.Width() + lWAdjust;
  823.             lHeight = (int32)crFrame.Height() + lHAdjust;
  824.         }
  825.         else {
  826.             lWidth = (int32)crFrame.Width();
  827.             lHeight = (int32)crFrame.Height();
  828.         }
  829.  
  830.         if (pChrome->location_is_chrome) {
  831.             lLeft = pChrome->l_hint;
  832.             lTop = pChrome->t_hint;
  833.         }
  834.         else {
  835.             lLeft = (int32)crFrame.left;
  836.             lTop = (int32)crFrame.top;
  837.         }
  838.  
  839.         //There is a security problem where the window size buffer can be 
  840.         //overridden on Win95.  Using arbitrary max window size of 10000
  841.         lWidth = lWidth > 10000 ? 10000 : lWidth;
  842.         lHeight = lHeight > 10000 ? 10000 : lHeight;
  843.  
  844.         if (pChrome->topmost)
  845.             pWinCX->GetFrame()->GetFrameWnd()->SetWindowPos(&CWnd::wndTopMost, CASTINT(lLeft), CASTINT(lTop), CASTINT(lWidth), CASTINT(lHeight), NULL);
  846.         else if (pChrome->bottommost)
  847.             pWinCX->GetFrame()->GetFrameWnd()->SetWindowPos(&CWnd::wndBottom, CASTINT(lLeft), CASTINT(lTop), CASTINT(lWidth), CASTINT(lHeight), NULL);
  848.         else
  849.             pWinCX->GetFrame()->GetFrameWnd()->MoveWindow(CASTINT(lLeft), CASTINT(lTop), CASTINT(lWidth), CASTINT(lHeight));
  850.  
  851.         //  Specific width and height information means that we should not save the sizes when closing down, regardless of context type.
  852.         pWinCX->m_bSizeIsChrome = TRUE;
  853.     }
  854.  
  855.     //    Set windows always on bottom.
  856.     pWinCX->SetZOrder(pChrome->z_lock, pChrome->bottommost);
  857.  
  858.     //    Hotkeys
  859.     pWinCX->DisableHotkeys(pChrome->disable_commands);
  860.  
  861.     //    Scroll bars.
  862.     if(pChrome->show_scrollbar == FALSE)    {
  863.         //    Turn them off.
  864.         pWinCX->SetDynamicScrollBars(FALSE);
  865.         pWinCX->ShowScrollBars(SB_BOTH, FALSE);
  866.         pWinCX->SetAlwaysShowScrollBars(FALSE);
  867.     }
  868.     else {
  869.         pWinCX->SetDynamicScrollBars(TRUE);
  870.         pWinCX->RealizeScrollBars();
  871.     }
  872.  
  873.     //    Resize.
  874.     //    This is a truly gross and unholy option.
  875.     pWinCX->EnableResize(pChrome->allow_resize);
  876.  
  877.     //    Close.
  878.     //    This is a truly gross and unholy option.
  879.     //    This is reenabled in FE_DestroyContext regardless (i.e.
  880.     //        can't be closed unless someone calls that API).
  881.     //  This also sets the closing attributes of all child contexts.
  882.     pWinCX->EnableClose(pChrome->allow_close);
  883.  
  884.     //    Close callback.
  885.     //    Callback when the context is destroyed.
  886.     pWinCX->CloseCallback(pChrome->close_callback, pChrome->close_arg);
  887.  
  888.     //  We don't handle modality, as there is no parent context passed in.
  889. }
  890.  
  891. //  Query current chrome in a context.
  892. void FE_QueryChrome(MWContext *pContext, Chrome *pChrome)
  893. {
  894.     TRACE("FE_QueryChrome(%p, %p)\n", pContext, pChrome);
  895.  
  896.     //  API fulfillments.
  897.     if(!pContext || !pChrome || !ABSTRACTCX(pContext) || !ABSTRACTCX(pContext)->IsFrameContext())   {
  898.         return;
  899.     }
  900.  
  901.     CWinCX *pWinCX = WINCX(pContext);
  902.     if(!pWinCX->GetPane() || !pWinCX->GetDocument() || !pWinCX->GetFrame() || !pWinCX->GetFrame()->GetFrameWnd())    {
  903.         //  Context isn't anatomically correct.
  904.         return;
  905.     }
  906.  
  907.     //  Clear the chrome struct, we'll refill in the relevant parts.
  908.     memset((void *)pChrome, 0, sizeof(Chrome));
  909.  
  910.     LPCHROME pIChrome = pWinCX->GetFrame()->GetChrome();
  911.     if(pIChrome) {
  912.         //    Toolbar on or off?
  913.         pChrome->show_button_bar = pIChrome->GetToolbarVisible(ID_NAVIGATION_TOOLBAR);
  914.  
  915.         //    Url bar and directory buttons.
  916.         pChrome->show_url_bar = pIChrome->GetToolbarVisible(ID_LOCATION_TOOLBAR);
  917.         pChrome->show_directory_buttons = pIChrome->GetToolbarVisible(ID_PERSONAL_TOOLBAR);
  918.  
  919.         //    The security bar?
  920.         //  TODO: Fix me!
  921.         pChrome->show_security_bar = TRUE;
  922.  
  923.         //    Status bar!
  924.         LPNSSTATUSBAR pIStatusBar = NULL;
  925.         pIChrome->QueryInterface( IID_INSStatusBar, (LPVOID *) &pIStatusBar );
  926.         if ( pIStatusBar ) {
  927.             HWND hWnd = pIStatusBar->GetHWnd();
  928.             pIStatusBar->Release();
  929.             pChrome->show_bottom_status_bar = IsWindowVisible( hWnd );
  930.         }
  931.     }
  932.  
  933.     //    Show the menu?
  934.     pChrome->show_menu = pWinCX->GetFrame()->GetFrameWnd()->GetMenu() == NULL ? FALSE : TRUE;
  935.  
  936.     //    Size, of all things, of the viewing area only....
  937.     //    Acount for the view border style, too.
  938.     CRect crView;
  939.     ::GetWindowRect(pWinCX->GetPane(), crView);
  940.     CRect crFrame;
  941.     pWinCX->GetFrame()->GetFrameWnd()->GetWindowRect(crFrame);
  942.     crView.InflateRect(-1 * sysInfo.m_iBorderWidth, -1 * sysInfo.m_iBorderHeight);
  943.     pChrome->outw_hint = (int32)crFrame.Width();
  944.     pChrome->outh_hint = (int32)crFrame.Height();
  945.     pChrome->w_hint = (int32)crView.Width();
  946.     pChrome->h_hint = (int32)crView.Height();
  947.     pChrome->l_hint = (int32)crFrame.left;
  948.     pChrome->t_hint = (int32)crFrame.top;
  949.  
  950.     //Set to make sure the coords given are used.
  951.     pChrome->location_is_chrome= TRUE;
  952.  
  953.     //    Scroll bars.
  954.     pChrome->show_scrollbar = pWinCX->DynamicScrollBars();
  955.  
  956.     //    Resize.
  957.     //    This is a truly gross and unholy option.
  958.     pChrome->allow_resize = ((CGenericFrame *)pWinCX->GetFrame()->GetFrameWnd())->CanResize();
  959.  
  960.     //    Hotkeys.
  961.     pChrome->disable_commands = ((CGenericFrame *)pWinCX->GetFrame()->GetFrameWnd())->HotkeysDisabled();
  962.  
  963.     //    ZLocked.
  964.     pChrome->z_lock = ((CGenericFrame *)pWinCX->GetFrame()->GetFrameWnd())->IsZOrderLocked();
  965.  
  966.     //    Bottommost.
  967.     pChrome->bottommost = ((CGenericFrame *)pWinCX->GetFrame()->GetFrameWnd())->IsBottommost();
  968.  
  969.     //    Close.
  970.     //    This is a truly gross and unholy option.
  971.     //  This will only report if the current context and its children can close, not if
  972.     //      the actual frame can close if this context has a parent.
  973.     pChrome->allow_close = pWinCX->GetDocument()->CanClose();
  974.  
  975.     //    Close callback is not handled correctly, as there may be multiples.
  976.  
  977.     //  We don't handle modality, as there is no parent context passed in to check against.
  978. }
  979.  
  980. //    Destroy a window/context.
  981. void FE_DestroyWindow(MWContext *pContext)
  982. {
  983.     TRACE("FE_DestroyWindow(%p)\n", pContext);
  984.  
  985.     ASSERT(pContext);
  986.     if(pContext != NULL)    {
  987.         //    Make sure that this is a CWinCX.
  988.         ASSERT(ABSTRACTCX(pContext)->IsFrameContext());
  989.         if(ABSTRACTCX(pContext)->IsWindowContext())    {
  990.             CWinCX *pCX = WINCX(pContext);
  991.  
  992.             //    Make sure there's a frame to close.
  993.             if(pCX->GetFrame()->GetFrameWnd())    {
  994.                 //    Reenable closing.
  995.                 pCX->EnableClose(TRUE);
  996.  
  997.                 //    Send it a close message.
  998.                 pCX->GetFrame()->GetFrameWnd()->SendMessage(WM_CLOSE);
  999.             }
  1000.         }
  1001.     }
  1002. }
  1003.  
  1004. //  Fill in left top position of frame.
  1005. //  Breaks down on the minimized maximized scenario.
  1006. void FE_GetWindowPosition(MWContext *pContext, int32 *pX, int32 *pY)
  1007. {
  1008.     TRACE("FE_GetWindowPosition(%p, %p, %p)\n", pContext, pX, pY);
  1009.  
  1010.     //  Initialize.
  1011.     if(pX)  {
  1012.         *pX = 0;
  1013.     }
  1014.     if(pY)  {
  1015.         *pY = 0;
  1016.     }
  1017.     
  1018.     if(pContext && ABSTRACTCX(pContext) && ABSTRACTCX(pContext)->IsFrameContext() && (pX || pY))    {
  1019.         //    Make sure there's a frame.
  1020.         CWinCX *pCX = WINCX(pContext);
  1021.         if(pCX->GetFrame() && pCX->GetFrame()->GetFrameWnd())    {
  1022.             CRect cr;
  1023.             pCX->GetFrame()->GetFrameWnd()->GetWindowRect(cr);
  1024.  
  1025.             if(pX)  {
  1026.                 *pX = cr.left;
  1027.             }
  1028.             if(pY)  {
  1029.                 *pY = cr.top;
  1030.             }
  1031.         }
  1032.     }
  1033. }
  1034.  
  1035. //  Set left top position of frame.
  1036. //  Breaks down on the minimized maximized scenario.
  1037. void FE_SetWindowPosition(MWContext *pContext, int32 lX, int32 lY)
  1038. {
  1039.     TRACE("FE_SetWindowPosition(%p, %ld, %ld)\n", pContext, lX, lY);
  1040.  
  1041.     if(pContext && ABSTRACTCX(pContext) &&
  1042.         ABSTRACTCX(pContext)->IsFrameContext())    {
  1043.         //    Make sure there's a frame.
  1044.         CWinCX *pCX = WINCX(pContext);
  1045.         if(pCX->GetFrame() && pCX->GetFrame()->GetFrameWnd())    {
  1046.             pCX->GetFrame()->GetFrameWnd()->SetWindowPos(NULL, CASTINT(lX),
  1047.                 CASTINT(lY), 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
  1048.         }
  1049.     }
  1050. }
  1051.  
  1052. //  Return screen dimensions.
  1053. void FE_GetScreenSize(MWContext *pContext, int32 *pX, int32 *pY)
  1054. {
  1055.     //  Initialize
  1056.     if(pX)  {
  1057.         *pX = sysInfo.m_iScreenWidth;
  1058.     }
  1059.     if(pY)  {
  1060.         *pY = sysInfo.m_iScreenHeight;
  1061.     }
  1062. }
  1063.  
  1064. //  Return available screen rectangle.
  1065. void FE_GetAvailScreenRect(MWContext *pContext, int32 *pX, int32 *pY, 
  1066.                         int32 *pLeft, int32 *pTop)
  1067. {
  1068.     RECT *pRect = NULL;
  1069. #ifdef WIN32
  1070.     APPBARDATA abd;
  1071.     UINT state;
  1072.  
  1073.     XP_BZERO(&abd, sizeof abd);
  1074.     abd.cbSize = sizeof(abd);
  1075.     abd.hWnd = NULL;
  1076.  
  1077.     state = SHAppBarMessage(ABM_GETSTATE, &abd);
  1078.  
  1079.     if ((state & ABS_ALWAYSONTOP) && !(state & ABS_AUTOHIDE))
  1080.     if (!SHAppBarMessage(ABM_GETTASKBARPOS, &abd))
  1081.         ASSERT(0);
  1082.     pRect = &abd.rc;
  1083. #endif
  1084.     //  Initialize
  1085.     if(pX)  {
  1086.         *pX = sysInfo.m_iScreenWidth;
  1087.     if (pRect != NULL) {
  1088.         if (pRect->top < 0 && pRect->bottom > sysInfo.m_iScreenHeight) {
  1089.         //Docked left
  1090.         if (pRect->left < 0)
  1091.             *pX -= pRect->right;
  1092.         //Docked right
  1093.         if (pRect->right > sysInfo.m_iScreenWidth)
  1094.             *pX = pRect->left;
  1095.         }
  1096.     }
  1097.     }
  1098.     if(pY)  {
  1099.         *pY = sysInfo.m_iScreenHeight;
  1100.     if (pRect != NULL) {
  1101.         if (pRect->left < 0 && pRect->right > sysInfo.m_iScreenWidth) {
  1102.         //Docked top
  1103.         if (pRect->top < 0);
  1104.             *pY -= pRect->bottom;
  1105.         //Docked bottom
  1106.         if (pRect->bottom > sysInfo.m_iScreenHeight)
  1107.             *pY = pRect->top;
  1108.         }
  1109.     }
  1110.     }
  1111.     if(pLeft)  {
  1112.         *pLeft = 0;
  1113.     if (pRect != NULL) {
  1114.         if (pRect->top < 0 && pRect->left < 0) {
  1115.         //Docked left
  1116.         if (pRect->bottom > sysInfo.m_iScreenHeight)
  1117.             *pLeft = pRect->right;
  1118.         }
  1119.     }
  1120.     }
  1121.     if(pTop)  {
  1122.         *pTop = 0;
  1123.     if (pRect != NULL) {
  1124.         if (pRect->top < 0 && pRect->left < 0) {
  1125.         //Docked top
  1126.         if (pRect->right > sysInfo.m_iScreenWidth)
  1127.             *pTop = pRect->bottom;
  1128.         }
  1129.     }
  1130.     }
  1131. }
  1132.  
  1133. //  Return color depth.
  1134. void FE_GetPixelAndColorDepth(MWContext *pContext, int32 *pixel, int32 *pallette)
  1135. {
  1136.     TRACE("FE_GetPixelAndColorDepth(%p, %p)\n", pixel, pallette);
  1137.  
  1138.     *pixel = *pallette = 0;
  1139.  
  1140.     if(ABSTRACTCX(pContext)->IsDestroyed() == FALSE) {
  1141.  
  1142.     CWinCX *pWinCX = WINCX(pContext);
  1143.  
  1144.     HDC pDC = pWinCX->GetContextDC();
  1145.  
  1146.     //  Figure out the depth of the CDC.
  1147.     *pixel = ::GetDeviceCaps(pDC, BITSPIXEL);
  1148.  
  1149.     //  Check for pallette existence
  1150.         if ((::GetDeviceCaps(pDC, RASTERCAPS) & RC_PALETTE) != 0)
  1151.         *pallette = ::GetDeviceCaps(pDC, COLORRES);
  1152.     else
  1153.         *pallette = *pixel;
  1154.  
  1155.     pWinCX->ReleaseContextDC(pDC);
  1156.     }
  1157.  
  1158. }
  1159.  
  1160.  
  1161.  
  1162.  
  1163.  
  1164.  
  1165.  
  1166.  
  1167. BOOL GetIntelCPUSpeed(int32 &processorSpeed );
  1168. BOOL GetIntelCPUInfoViaCPUID(char *systemArchitecture,
  1169.             int32 &processorType, int32 &processorFamily, 
  1170.             int32 &processorModel, int32 &processorStepping, int32 &processorFeatures,
  1171.             CString &vendor);
  1172. #ifndef _WIN32
  1173. unsigned short GetBaseMemC();
  1174. unsigned short GetExpMemC();
  1175. #endif
  1176. CString csUNKNOWN = "Unknown";
  1177. CString csINTEL = "Intel";
  1178. CString csMIPS = "Mips";
  1179. CString csALPHA = "Alpha";
  1180. CString csPPC = "PowerPC";
  1181.  
  1182. CString csARCHITECTURE = "ARCHITECTURE";
  1183. CString csFAMILY = "FAMILY";
  1184. CString csMODEL = "MODEL";
  1185. CString csSTEPPING = "STEPPING";
  1186. CString csTYPE = "TYPE";
  1187. CString csFEATURES = "FEATURES";
  1188. CString csPASS = "PASS";
  1189. CString csREVISION = "REVISION";
  1190. CString csVERSION = "VERSION";
  1191. CString csVENDOR = "VENDOR";
  1192.  
  1193. // VARIABLE STRUCTURE DEFINITIONS //////////////////////////////
  1194. struct FREQ_INFO
  1195. {
  1196.     unsigned long in_cycles;    // Internal clock cycles during
  1197.                                 //   test
  1198.                                 
  1199.     unsigned long ex_ticks;        // Microseconds elapsed during 
  1200.                                 //   test
  1201.                                 
  1202.     unsigned long raw_freq;        // Raw frequency of CPU in MHz
  1203.     
  1204.     unsigned long norm_freq;    // Normalized frequency of CPU
  1205.                                 //   in MHz.
  1206. };
  1207.  
  1208. struct FREQ_INFO cpuspeed(int clocks);
  1209. // Function Prototypes /////////////////////////////////////////
  1210.  
  1211. /***************************************************************
  1212. * WORD wincpuidsupport()
  1213. * =================================
  1214. * Wincpuidsupport() tells the caller whether the host processor
  1215. * supports the CPUID opcode or not.
  1216. *
  1217. * Inputs: none
  1218. *
  1219. * Returns:
  1220. *  1 = CPUID opcode is supported
  1221. *  0 = CPUID opcode is not supported
  1222. ***************************************************************/
  1223.  
  1224. WORD wincpuidsupport();
  1225.  
  1226.  
  1227. /***************************************************************
  1228. * WORD wincpuid()
  1229. * ===============
  1230. * This routine uses the standard Intel assembly code to 
  1231. * determine what type of processor is in the computer, as
  1232. * described in application note AP-485 (Intel Order #241618).
  1233. * Wincpuid() returns the CPU type as an integer (that is, 
  1234. * 2 bytes, a WORD) in the AX register.
  1235. *
  1236. * Returns:
  1237. *  0 = 8086/88
  1238. *  2 = 80286
  1239. *  3 = 80386
  1240. *  4 = 80486
  1241. *  5 = Pentium(R) Processor
  1242. *  6 = PentiumPro(R) Processor
  1243. *  7 or higher = Processor beyond the PentiumPro6(R) Processor
  1244. *
  1245. *  Note: This function also sets the global variable clone_flag
  1246. ***************************************************************/
  1247. WORD  wincpuid();
  1248.  
  1249.  
  1250. /***************************************************************
  1251. * WORD wincpuidext()
  1252. * ==================
  1253. * Similar to wincpuid(), but returns more data, in the order
  1254. * reflecting the actual output of a CPUID instruction execution:
  1255. *
  1256. * Returns:
  1257. * AX(15:14) = Reserved (mask these off in the calling code 
  1258. *                before using)
  1259. * AX(13:12) = Processor type (00=Standard OEM CPU, 01=OverDrive,
  1260. *                10=Dual CPU, 11=Reserved)
  1261. * AX(11:8)  = CPU Family (the same 4-bit quantity as wincpuid())
  1262. * AX(7:4)   = CPU Model, if the processor supports the CPUID 
  1263. *                opcode; zero otherwise
  1264. * AX(3:0)   = Stepping #, if the processor supports the CPUID 
  1265. *                opcode; zero otherwise
  1266. *
  1267. *  Note: This function also sets the global variable clone_flag
  1268. ***************************************************************/
  1269. WORD wincpuidext(CString &vendorName);
  1270.  
  1271.  
  1272. /***************************************************************
  1273. * DWORD wincpufeatures()
  1274. * ======================
  1275. * Wincpufeatures() returns the CPU features flags as a DWORD 
  1276. *    (that is, 32 bits).
  1277. *
  1278. * Inputs: none
  1279. *
  1280. * Returns:
  1281. *   0 = Processor which does not execute the CPUID instruction.
  1282. *          This includes 8086, 8088, 80286, 80386, and some 
  1283. *           older 80486 processors.                       
  1284. *
  1285. * Else
  1286. *   Feature Flags (refer to App Note AP-485 for description).
  1287. *      This DWORD was put into EDX by the CPUID instruction.
  1288. *
  1289. *    Current flag assignment is as follows:
  1290. *
  1291. *        bit31..10   reserved (=0)
  1292. *        bit9=1      CPU contains a local APIC (iPentium-3V)
  1293. *        bit8=1      CMPXCHG8B instruction supported
  1294. *        bit7=1      machine check exception supported
  1295. *        bit6=0      reserved (36bit-addressing & 2MB-paging)
  1296. *        bit5=1      iPentium-style MSRs supported
  1297. *        bit4=1      time stamp counter TSC supported
  1298. *        bit3=1      page size extensions supported
  1299. *        bit2=1      I/O breakpoints supported
  1300. *        bit1=1      enhanced virtual 8086 mode supported
  1301. *        bit0=1      CPU contains a floating-point unit (FPU)
  1302. *
  1303. *    Note: New bits will be assigned on future processors... see
  1304. *         processor data books for updated information
  1305. *
  1306. *    Note: This function also sets the global variable clone_flag
  1307. ***************************************************************/
  1308. DWORD wincpufeatures(CString &vendorName);
  1309.  
  1310.  
  1311.  
  1312. #ifndef _WIN32
  1313. unsigned short GetBaseMemC()
  1314. {
  1315.     // get memory below 1-MB boundary
  1316.     // using run-time library functions
  1317.     unsigned short base;
  1318.     outp( 0x70, 0x15 );
  1319.     base = inp( 0x71 ); //retrieve low byte
  1320.     outp( 0x70, 0x16 ); 
  1321.     base += inp(0x71) << 8; //retieve high byte,
  1322.                             //shift and add to base
  1323.     return base;  // return K's of base memory
  1324. }
  1325.  
  1326. unsigned short GetExpMemC()
  1327. {
  1328.     // get memory above 1-MB boundary
  1329.     // using run-time library functions
  1330.     unsigned short extend;
  1331.     outp( 0x70, 0x17 );
  1332.     base = inp( 0x71 ); //retrieve low byte
  1333.     outp( 0x70, 0x18 ); 
  1334.     base += inp(0x71) << 8; //retieve high byte,
  1335.                             //shift and add to extend
  1336.     return extend;  // return K's of expansion memory        
  1337. }
  1338. #endif
  1339.  
  1340. int32 FE_SystemRAM( void )
  1341. {
  1342.     int32 systemRAM = -1;
  1343. #ifdef _WIN32
  1344.     MEMORYSTATUS MemoryStatus;
  1345.  
  1346.     memset( &MemoryStatus, 0, sizeof(MEMORYSTATUS));
  1347.     MemoryStatus.dwLength = sizeof(MEMORYSTATUS);
  1348.  
  1349.     GlobalMemoryStatus( &MemoryStatus );
  1350.     //return physical memory size in K
  1351.     systemRAM = MemoryStatus.dwTotalPhys / 1024 ;
  1352. #else
  1353.     //return physical memory size in K
  1354.     int32 expansionMem = GetExpMemC();
  1355.     int32 baseMem = GetBaseMemC();
  1356.     systemRAM = expansionMem + baseMem;
  1357. #endif
  1358. return systemRAM;
  1359. }
  1360.  
  1361. int32 FE_SystemClockSpeed( void )
  1362. {
  1363.     int32 clockSpeed = -1;
  1364. #ifdef _WIN32
  1365.     OSVERSIONINFO OSVersionInfo;
  1366.     memset( &OSVersionInfo, 0, sizeof(OSVERSIONINFO));
  1367.     OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  1368.     if(GetVersionEx( &OSVersionInfo ))
  1369.     {
  1370.         if(OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ||
  1371.             OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) //Windows 9x
  1372.         {
  1373.             SYSTEM_INFO SystemInfo;
  1374.             GetSystemInfo( &SystemInfo );
  1375.             if( SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL )
  1376.             {
  1377.                 if(!GetIntelCPUSpeed(clockSpeed))
  1378.                     clockSpeed = -1;
  1379.             }
  1380.             else
  1381.             if( SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ALPHA )
  1382.             {
  1383.                 return -1;
  1384.             }
  1385.             else
  1386.             if( SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_MIPS )
  1387.             {
  1388.                 return -1;
  1389.             }
  1390.             else
  1391.             if( SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_PPC )
  1392.             {
  1393.                 return -1;
  1394.             }
  1395.             else
  1396.             if( SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_UNKNOWN )
  1397.                 return -1;
  1398.             else
  1399.             {
  1400.                 ASSERT(FALSE);
  1401.                 return -1;
  1402.             }
  1403.         }
  1404.         else //if Win32s we must be running on Win3.x so Intel architecture
  1405.         if(    OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32s )
  1406.         {
  1407.             if(!GetIntelCPUSpeed(clockSpeed))
  1408.                 clockSpeed = -1;
  1409.         }
  1410.         else
  1411.         {
  1412.             ASSERT(FALSE);
  1413.             return -1;
  1414.         }
  1415.     }
  1416. #else
  1417.     if(!GetIntelCPUSpeed(clockSpeed))
  1418.         clockSpeed = -1;
  1419. #endif
  1420.     return clockSpeed;
  1421. }
  1422.  
  1423. BOOL GetIntelCPUSpeed(int32 &processorSpeed )
  1424. {
  1425.     BOOL bRet = FALSE;
  1426.     // VARIABLE STRUCTURE DEFINITIONS //////////////////////////////
  1427.     struct FREQ_INFO cpu_speed;        // Return variable 
  1428.                                         //   structure for 
  1429.                                         //   cpuspeed 
  1430.                                         //   routine
  1431.             
  1432.             
  1433.     cpu_speed = cpuspeed(0);
  1434.                 
  1435.     if ( cpu_speed.in_cycles == 0 && cpu_speed.ex_ticks  == 0 )
  1436.     {
  1437.         /*             
  1438.          sprintf(buf,
  1439.                  "This processor cannot be accurately "
  1440.                  "timed with this program.\n The "
  1441.                  "processor could be"
  1442.                  "below 80386 level.");
  1443.          MessageBox(NULL,buf,"error", MB_ICONINFORMATION );
  1444.          */
  1445.         bRet = FALSE;
  1446.     }
  1447.     else
  1448.     {
  1449.         /*
  1450.         sprintf(buf,
  1451.                 "Clock Cycles: %lu cycles\n"
  1452.                 "Elapsed Time: %luus\n"
  1453.                 "Raw Clock Frequency: %luMHz\n"
  1454.                 "Normalized Frequency: %luMHz",
  1455.                 cpu_speed.in_cycles,
  1456.                 cpu_speed.ex_ticks,
  1457.                 cpu_speed.raw_freq,
  1458.                 cpu_speed.norm_freq);          
  1459.  
  1460.         MessageBox(NULL,buf,"32-bit cpuspeed", 
  1461.                     MB_ICONINFORMATION );
  1462.         */
  1463.         processorSpeed = cpu_speed.norm_freq;
  1464.         bRet = TRUE;
  1465.     }
  1466.     return bRet;
  1467. }
  1468.  
  1469.  
  1470. BOOL GetIntelCPUInfoViaCPUID(CString &systemArchitecture,
  1471.             int32 &processorType, int32 &processorFamily, 
  1472.             int32 &processorModel, int32 &processorStepping, int32 &processorFeatures,
  1473.             CString &vendor)
  1474. {
  1475.     //Intel Only!!!
  1476.     systemArchitecture = csINTEL;
  1477.     int32 processorExtensions = 0;
  1478.     processorExtensions = wincpuidext(vendor);
  1479.  
  1480.     processorStepping = processorExtensions & 0x0f;        
  1481.     processorModel = (processorExtensions & 0x0f0) >> 4;
  1482.     processorFamily = (processorExtensions & 0x0f00) >> 8;
  1483.     processorType = (processorExtensions & 0x03000) >> 12;
  1484.  
  1485.     processorFeatures = wincpufeatures(vendor);
  1486.  
  1487.     return TRUE;
  1488. }
  1489.  
  1490. char *CreateNonIntelCPUInfoString(CString &systemArchitecture,
  1491.                                   int32 &processorModel, int32 &processorStepping)
  1492. {
  1493.     CString tmpStr;
  1494.     CString CPUInfoString;
  1495.     ASSERT( !systemArchitecture.IsEmpty() );
  1496.  
  1497.     if( !systemArchitecture.IsEmpty() )
  1498.     {
  1499.         CPUInfoString = csARCHITECTURE + "=";
  1500.         CPUInfoString += systemArchitecture;
  1501.     }
  1502.  
  1503.     if( systemArchitecture == csALPHA )
  1504.     {
  1505.         if( processorModel > -1 )
  1506.         {
  1507.             if( !CPUInfoString.IsEmpty() )
  1508.                 CPUInfoString += ";";
  1509.             CPUInfoString += csMODEL + "=A";
  1510.             tmpStr.Format("%.2X", processorModel );
  1511.             CPUInfoString += tmpStr;
  1512.         }
  1513.         if( processorStepping > -1 )
  1514.         {
  1515.             if( !CPUInfoString.IsEmpty() )
  1516.                 CPUInfoString += ";"; 
  1517.             CPUInfoString += csPASS + "=";
  1518.             tmpStr.Format("%.2X", processorStepping);
  1519.             CPUInfoString += tmpStr;
  1520.         }
  1521.     }
  1522.     else
  1523.     if( systemArchitecture == csMIPS )
  1524.     {
  1525.         if( processorModel > -1 )
  1526.         {
  1527.             if( !CPUInfoString.IsEmpty() )
  1528.                 CPUInfoString += ";";
  1529.             CPUInfoString += csREVISION + "=";
  1530.             tmpStr.Format("%.2X", processorModel);
  1531.             CPUInfoString += tmpStr;
  1532.         }
  1533.     }
  1534.     else
  1535.     if( systemArchitecture == csPPC )
  1536.     {
  1537.         if( processorModel > -1 )
  1538.         {
  1539.             if( !CPUInfoString.IsEmpty() )
  1540.                 CPUInfoString += ";";
  1541.             CPUInfoString += csVERSION + "=";
  1542.             tmpStr.Format("%.2X", processorModel);
  1543.             CPUInfoString += tmpStr;
  1544.         }
  1545.  
  1546.         if( processorStepping > -1 )
  1547.         {        
  1548.             CPUInfoString += ".";
  1549.             tmpStr.Format("%.2X", processorStepping);
  1550.             CPUInfoString += tmpStr;
  1551.         }
  1552.     }
  1553.     char * pstr = NULL;
  1554.     int len = CPUInfoString.GetLength();
  1555.     if(len > 0 )
  1556.     {
  1557.         pstr = new char[ len + 1];
  1558.         if( pstr != NULL )
  1559.             strcpy( pstr, CPUInfoString );
  1560.     }    
  1561.     return pstr;
  1562. }
  1563.             
  1564.             
  1565. char *CreateIntelCPUInfoString(CString &systemArchitecture,
  1566.             int32 processorType, int32 processorFamily, 
  1567.             int32 processorModel, int32 processorStepping, int32 processorFeatures,
  1568.             CString &vendor)
  1569. {
  1570.     CString tmpStr;
  1571.     CString CPUInfoString;
  1572.     ASSERT( !systemArchitecture.IsEmpty() );
  1573.  
  1574.     if( !systemArchitecture.IsEmpty() )
  1575.     {
  1576.         CPUInfoString = csARCHITECTURE + "=";
  1577.         CPUInfoString += systemArchitecture;
  1578.     }
  1579.     if( processorType > -1 )
  1580.     {
  1581.         if( !CPUInfoString.IsEmpty() )
  1582.             CPUInfoString += ";";
  1583.         CPUInfoString += csTYPE + "=";
  1584.         tmpStr.Format("%d", processorType);
  1585.         CPUInfoString += tmpStr;
  1586.     }
  1587.     if( processorFamily > -1 )
  1588.     {
  1589.         if( !CPUInfoString.IsEmpty() )
  1590.             CPUInfoString += ";";
  1591.         CPUInfoString += csFAMILY + "=";
  1592.         tmpStr.Format("%d", processorFamily);
  1593.         CPUInfoString += tmpStr;
  1594.     }
  1595.     if( processorModel > -1 )
  1596.     {
  1597.         if( !CPUInfoString.IsEmpty() )
  1598.             CPUInfoString += ";";
  1599.         CPUInfoString += csMODEL + "=";
  1600.         tmpStr.Format("%d", processorModel);
  1601.         CPUInfoString += tmpStr;
  1602.     }
  1603.     if( processorStepping > -1 )
  1604.     {
  1605.         if( !CPUInfoString.IsEmpty() )
  1606.             CPUInfoString += ";";
  1607.         CPUInfoString += csSTEPPING + "=";
  1608.         tmpStr.Format("%d", processorStepping);
  1609.         CPUInfoString += tmpStr;
  1610.     }
  1611.     if( processorFeatures > -1 )
  1612.     {
  1613.         if( !CPUInfoString.IsEmpty() )
  1614.             CPUInfoString += ";";
  1615.         CPUInfoString += csFEATURES + "=";
  1616.         tmpStr.Format("0x%x", processorFeatures);
  1617.         CPUInfoString += tmpStr;
  1618.     }
  1619.  
  1620.     if( !CPUInfoString.IsEmpty() )
  1621.         CPUInfoString += ";";
  1622.     CPUInfoString += csVENDOR + "=";
  1623.     if( !vendor.IsEmpty() )
  1624.         CPUInfoString += vendor;
  1625.     else
  1626.         CPUInfoString += csUNKNOWN;
  1627.  
  1628.     char * pstr = NULL;
  1629.     int len = CPUInfoString.GetLength();
  1630.     if(len > 0 )
  1631.     {
  1632.         pstr = new char[ len + 1];
  1633.         if( pstr != NULL )
  1634.             strcpy( pstr, CPUInfoString );
  1635.     }
  1636.     
  1637.     return pstr;
  1638. }
  1639.  
  1640. char *FE_SystemCPUInfo(void)
  1641. {
  1642.     CString systemArchitecture;
  1643.     int32 processorType = -1; 
  1644.     int32 processorFamily = -1; 
  1645.     int32 processorModel = -1; 
  1646.     int32 processorStepping = -1; 
  1647.     int32 processorFeatures = -1;
  1648.     CString vendor;
  1649.  
  1650. #ifdef _WIN32
  1651.     OSVERSIONINFO OSVersionInfo;
  1652.     memset( &OSVersionInfo, 0, sizeof(OSVERSIONINFO));
  1653.     OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  1654.     if(GetVersionEx( &OSVersionInfo ))
  1655.     {
  1656.         //if Win32s is the platform
  1657.         if(    OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32s )
  1658.         {
  1659.                 if(GetIntelCPUInfoViaCPUID(systemArchitecture,    
  1660.                             processorType, processorFamily, processorModel, 
  1661.                             processorStepping, processorFeatures, vendor ))
  1662.                     return CreateIntelCPUInfoString(systemArchitecture,    
  1663.                             processorType, processorFamily, processorModel, 
  1664.                             processorStepping, processorFeatures, vendor );
  1665.                 else
  1666.                     return NULL;
  1667.         }
  1668.         else
  1669.         if(OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ||
  1670.             OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) //Windows 9x
  1671.         {
  1672.             SYSTEM_INFO SystemInfo;
  1673.             GetSystemInfo( &SystemInfo );
  1674.             processorFamily = SystemInfo.wProcessorLevel;
  1675.             if( SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL )
  1676.             {    
  1677.                 if(OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) 
  1678.                 {    //Windows 9x
  1679.                     if(GetIntelCPUInfoViaCPUID(systemArchitecture,    
  1680.                             processorType, processorFamily, processorModel, 
  1681.                             processorStepping, processorFeatures, vendor ))
  1682.                         return CreateIntelCPUInfoString(systemArchitecture,    
  1683.                             processorType, processorFamily, processorModel, 
  1684.                             processorStepping, processorFeatures, vendor );
  1685.                     else
  1686.                         return NULL;
  1687.                 }
  1688.                 else //Windows NT on Intel
  1689.                 {
  1690.                     //Might as well use CPUID; it provides a little more information
  1691.                     if(GetIntelCPUInfoViaCPUID(systemArchitecture,    
  1692.                             processorType, processorFamily, processorModel, 
  1693.                             processorStepping, processorFeatures, vendor ))
  1694.                         return CreateIntelCPUInfoString(systemArchitecture,    
  1695.                             processorType, processorFamily, processorModel, 
  1696.                             processorStepping, processorFeatures, vendor );
  1697.                     else
  1698.                         return NULL;
  1699.                     
  1700.     //                strcpy(systemArchitecture, INTEL);
  1701.     //                if( SystemInfo.dwProcessorType == PROCESSOR_INTEL_386 ||
  1702.     //                    SystemInfo.dwProcessorType == PROCESSOR_INTEL_486 )
  1703.     //                {
  1704.     //                    //wProcessor type of form xxyz; if xx != 0xFF
  1705.     //                    if( ((SystemInfo.wProcessorRevision >> 8) & 0xff ) != 0xff )
  1706.     //                    {
  1707.     //                        //then xx + 'A' is the stepping letter                        
  1708.     //                        processorStepping = ((SystemInfo.wProcessorRevision >> 8) & 0xff) + 'A';
  1709.     //                        //this is actually the minor stepping
  1710.     //                        processorModel = (SystemInfo.wProcessorRevision & 0x0ff);
  1711.     //                    }
  1712.     //                    else
  1713.     //                    if( ((SystemInfo.wProcessorRevision >> 8) & 0xff ) == 0xff )
  1714.     //                    {
  1715.     //                        processorModel = (SystemInfo.wProcessorRevision & 0x0f0) >> 4;
  1716.     //                        processorStepping = (SystemInfo.wProcessorRevision & 0x0f);
  1717.     //                    }
  1718.     //                }
  1719.     //                else  //processor must be > x486
  1720.     //                {
  1721.     //                    processorModel = (SystemInfo.wProcessorRevision & 0x0ff00) >> 8;
  1722.     //                    processorStepping = (SystemInfo.wProcessorRevision & 0x0ff);
  1723.     //                }
  1724.                 }
  1725.             }
  1726.             else
  1727.             if( SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ALPHA )
  1728.             {
  1729.                 systemArchitecture = csALPHA;
  1730.                 processorModel = (SystemInfo.wProcessorRevision & 0x0ff00) >> 8;
  1731.                 //"Pass" on Alpha; display as "Model 'A'+xx, Pass yy"
  1732.                 processorStepping = (SystemInfo.wProcessorRevision & 0x0ff);
  1733.                 return CreateNonIntelCPUInfoString(systemArchitecture, 
  1734.                                             processorModel, processorStepping);
  1735.             }
  1736.             else
  1737.             if( SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_MIPS )
  1738.             {
  1739.                 systemArchitecture = csMIPS;
  1740.                 //"Revision Number" on MIPS
  1741.                 processorModel = (SystemInfo.wProcessorRevision & 0x0ff);
  1742.                 return CreateNonIntelCPUInfoString(systemArchitecture, 
  1743.                                             processorModel, processorStepping);
  1744.             }
  1745.             else
  1746.             if( SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_PPC )
  1747.             {
  1748.                 systemArchitecture = csPPC;
  1749.                 //display as xx.yy on PPC
  1750.                 processorModel = (SystemInfo.wProcessorRevision & 0x0ff00) >> 8;
  1751.                 processorStepping = (SystemInfo.wProcessorRevision & 0x0ff);
  1752.                 return CreateNonIntelCPUInfoString(systemArchitecture, 
  1753.                                             processorModel, processorStepping);
  1754.             }
  1755.             else
  1756.             if( SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_UNKNOWN )
  1757.             {
  1758.                 systemArchitecture = csUNKNOWN;
  1759.                 return CreateNonIntelCPUInfoString(systemArchitecture, 
  1760.                                             processorModel, processorStepping);
  1761.             }
  1762.             else
  1763.             {
  1764.                 ASSERT(FALSE);
  1765.                 systemArchitecture = csUNKNOWN;
  1766.                 return CreateNonIntelCPUInfoString(systemArchitecture, 
  1767.                                             processorModel, processorStepping);
  1768.             }            
  1769.         }
  1770.         ASSERT(FALSE); //Unknown operating system
  1771.     }
  1772.     return NULL;
  1773. #else //WIN16
  1774.     if(GetIntelCPUInfoViaCPUID(systemArchitecture, processorType, 
  1775.                             processorFamily, processorModel, processorStepping,
  1776.                             processorFeatures, vendor ))
  1777.         return CreateIntelCPUInfoString(systemArchitecture,    
  1778.                             processorType, processorFamily, processorModel, 
  1779.                             processorStepping, processorFeatures, vendor );
  1780.     else
  1781.         return NULL;
  1782. #endif
  1783. }
  1784.  
  1785.  
  1786.  
  1787.  
  1788.  
  1789.  
  1790.  
  1791.  
  1792. // CONSTANT DEFINITIONS ////////////////////////////////////////
  1793. #define CLONE_MASK        0x8000    // Mask to be 'OR'ed with proc-
  1794. #define MAXCLOCKS        150        // Maximum number of cycles per
  1795.                                 //   BSF instruction
  1796.     // ACCURACY AFFECTING CONSTANTS ////////////////////////////
  1797. #define ITERATIONS        4000    // Number of times to repeat BSF
  1798.                                 //   instruction in samplings.
  1799.                                 //   Initially set to 4000.
  1800.  
  1801. #define MAX_TRIES        20        // Maximum number of samplings
  1802.                                 //   to allow before giving up
  1803.                                 //   and returning current 
  1804.                                 //   average. Initially set to
  1805.                                 //   20.
  1806.     
  1807. #define TOLERANCE        1        // Number of MHz to allow
  1808.                                 //   samplings to deviate from
  1809.                                 //   average of samplings.
  1810.                                 //   Initially set to 2.
  1811.  
  1812. #define    SAMPLINGS        10        // Number of BSF sequence 
  1813.                                 //   samplings to make.
  1814.                                 //   Initially set to 10.
  1815.  
  1816.  
  1817. typedef unsigned short ushort;
  1818. typedef unsigned long  ulong;
  1819.  
  1820. // Global Variable /////////////////////////////////////////////
  1821. int clone_flag;                // Flag to show whether processor
  1822.                             //   is non-Intel
  1823.  
  1824.  
  1825.  
  1826.  
  1827. // OPCODE DEFINITIONS //////////////////////////////////////////
  1828. #define CPU_ID _asm _emit 0x0f _asm _emit 0xa2     
  1829.                                         // CPUID instruction
  1830.  
  1831. #define RDTSC  _asm _emit 0x0f _asm _emit 0x31    
  1832.                                         // RDTSC instruction
  1833.  
  1834. // Private Function Declarations ///////////////////////////////
  1835.  
  1836. /***************************************************************
  1837. * static WORD check_clone()
  1838. *
  1839. * Inputs: none
  1840. *
  1841. * Returns:
  1842. *   1      if processor is clone (limited detection ability)
  1843. *   0      otherwise
  1844. ***************************************************************/
  1845. static WORD check_clone();
  1846.  
  1847.  
  1848. /***************************************************************
  1849. * static WORD check_8086()
  1850. *
  1851. * Inputs: none
  1852. *
  1853. * Returns: 
  1854. *   0      if processor 8086
  1855. *   0xffff otherwise
  1856. ***************************************************************/
  1857. static WORD check_8086();
  1858.  
  1859.  
  1860. /***************************************************************
  1861. * static WORD check_80286()
  1862. *
  1863. * Inputs: none
  1864. *
  1865. * Returns:
  1866. *   2      if processor 80286
  1867. *   0xffff otherwise
  1868. ***************************************************************/
  1869. static WORD check_80286();
  1870.  
  1871.  
  1872. /***************************************************************
  1873. * static WORD check_80386()
  1874. *
  1875. * Inputs: none
  1876. *
  1877. * Returns:
  1878. *   3      if processor 80386
  1879. *   0xffff otherwise
  1880. ***************************************************************/
  1881. static WORD check_80386();
  1882.  
  1883.  
  1884. /***************************************************************
  1885. * static WORD check_IDProc()
  1886. * ==========================
  1887. * Check_IDProc() uses the CPUID opcode to find the family type
  1888. * of the host processor.
  1889. *
  1890. * Inputs: none
  1891. *
  1892. * Returns:
  1893. *  CPU Family (i.e. 4 if Intel 486, 5 if Pentium(R) Processor)
  1894. *
  1895. *  Note: This function also sets the global variable clone_flag
  1896. ***************************************************************/
  1897. static WORD check_IDProc();
  1898.  
  1899. //end of prototypes //////////////////////////////////////////////
  1900.  
  1901.  
  1902. #define ROUND_THRESHOLD        6
  1903.  
  1904. // Tabs set at 4
  1905. static struct FREQ_INFO GetRDTSCCpuSpeed();
  1906. static struct FREQ_INFO GetBSFCpuSpeed(ulong cycles);
  1907.  
  1908. // Number of cycles needed to execute a single BSF instruction.
  1909. //    Note that processors below i386(tm) are not supported.
  1910. static ulong processor_cycles[] = {
  1911.     00,  00,  00, 115, 47, 43, 
  1912.     38,  38,  38, 38,  38, 38, 
  1913. };
  1914.  
  1915. /***************************************************************
  1916. * wincpuidsupport()
  1917. *
  1918. * Inputs: none
  1919. *
  1920. * Returns:
  1921. *  1 = CPUID opcode is supported
  1922. *  0 = CPUID opcode is not supported
  1923. ***************************************************************/
  1924.  
  1925. WORD wincpuidsupport() {
  1926.     int cpuid_support = 1;
  1927.  
  1928.     _asm {
  1929.         pushfd                    // Get original EFLAGS
  1930.         pop        eax
  1931.         mov     ecx, eax
  1932.         xor     eax, 200000h    // Flip ID bit in EFLAGS
  1933.         push    eax                // Save new EFLAGS value on
  1934.                                 //   stack
  1935.         popfd                    // Replace current EFLAGS value
  1936.         pushfd                    // Get new EFLAGS
  1937.         pop     eax                // Store new EFLAGS in EAX
  1938.         xor     eax, ecx        // Can not toggle ID bit,
  1939.         jnz     support            // Processor=80486
  1940.         
  1941.         mov cpuid_support,0        // Clear support flag
  1942. support:
  1943.       }
  1944.     
  1945.     return cpuid_support;
  1946.  
  1947. } // wincpuidsupport()
  1948.  
  1949.  
  1950. /***************************************************************
  1951. * wincpuid()
  1952. *
  1953. * Inputs: none
  1954. *
  1955. * Returns:
  1956. *  0 = 8086/88
  1957. *  2 = 80286
  1958. *  3 = 80386
  1959. *  4 = 80486
  1960. *  5 = Pentium(R) Processor
  1961. *  6 = PentiumPro(R) Processor
  1962. *  7 or higher = Processor beyond the PentiumPro6(R) Processor
  1963. *
  1964. *  Note: This function also sets the global variable clone_flag
  1965. ***************************************************************/
  1966.  
  1967. WORD wincpuid() {
  1968.  
  1969.     WORD cpuid;
  1970.     
  1971.     if ( wincpuidsupport() )     // Determine whether CPUID 
  1972.                                 //   opcode is supported
  1973.         cpuid=check_IDProc();
  1974.  
  1975.     else {
  1976.         
  1977.         clone_flag=check_clone();
  1978.     
  1979.         cpuid=check_8086();            // Will return FFFFh or 0
  1980.         if (cpuid == 0) goto end;
  1981.     
  1982.         cpuid=check_80286();           // Will return FFFFh or 2
  1983.         if (cpuid == 2) goto end;
  1984.  
  1985.         cpuid=check_80386();           // Will return FFFFh or 3
  1986.         if (cpuid == 3) goto end;    // temporarily commented out.
  1987.         
  1988.         cpuid=4;        // If the processor does not support CPUID,
  1989.                         //  is not an 8086, 80286, or 80386, assign
  1990.                         //  processor to be an 80486
  1991.     }
  1992.  
  1993. end:
  1994.     if (clone_flag)
  1995.         cpuid = cpuid | CLONE_MASK;    // Signify that a clone has been
  1996.                                     //   detected by setting MSB high 
  1997.  
  1998.        return cpuid;
  1999.  
  2000. } // wincpuid ()
  2001.  
  2002.  
  2003. /***************************************************************
  2004. * wincpufeatures()
  2005. *
  2006. * Inputs: none
  2007. *
  2008. * Returns:
  2009. *   0 = Processor which does not execute the CPUID instruction.
  2010. *          This includes 8086, 8088, 80286, 80386, and some 
  2011. *           older 80486 processors.                       
  2012. *
  2013. * Else
  2014. *   Feature Flags (refer to App Note AP-485 for description).
  2015. *      This DWORD was put into EDX by the CPUID instruction.
  2016. *
  2017. *    Current flag assignment is as follows:
  2018. *
  2019. *        bit31..10   reserved (=0)
  2020. *        bit9=1      CPU contains a local APIC (iPentium-3V)
  2021. *        bit8=1      CMPXCHG8B instruction supported
  2022. *        bit7=1      machine check exception supported
  2023. *        bit6=0      reserved (36bit-addressing & 2MB-paging)
  2024. *        bit5=1      iPentium-style MSRs supported
  2025. *        bit4=1      time stamp counter TSC supported
  2026. *        bit3=1      page size extensions supported
  2027. *        bit2=1      I/O breakpoints supported
  2028. *        bit1=1      enhanced virtual 8086 mode supported
  2029. *        bit0=1      CPU contains a floating-point unit (FPU)
  2030. *
  2031. *    Note: New bits will be assigned on future processors... see
  2032. *         processor data books for updated information
  2033. *
  2034. *    Note: This function also sets the global variable clone_flag
  2035. ***************************************************************/
  2036.  
  2037. DWORD wincpufeatures(CString &vendorName) {
  2038.  
  2039.     int i=0;
  2040.     DWORD cpuff=0x00000000;
  2041.     BYTE vendor_id[]="------------";
  2042.     BYTE intel_id[]="GenuineIntel";
  2043.  
  2044.     if ( wincpuidsupport() ) {
  2045.  
  2046. _asm {      
  2047.  
  2048.         xor     eax, eax        // Set up for CPUID instruction
  2049.         
  2050.         CPU_ID                  // Get and save vendor ID
  2051.  
  2052.         mov     dword ptr vendor_id, ebx
  2053.         mov     dword ptr vendor_id[+4], edx
  2054.         mov     dword ptr vendor_id[+8], ecx
  2055. }
  2056. vendorName = vendor_id;
  2057.  
  2058. for (i=0;i<12;i++)
  2059. {
  2060.     if (!(vendor_id[i]==intel_id[i]))
  2061.         clone_flag = 1;    
  2062. }
  2063.  
  2064. _asm {
  2065.          
  2066.         cmp     eax, 1            // Make sure 1 is valid input 
  2067.                                 //   for CPUID
  2068.         
  2069.         jl      end_cpuff        // If not, jump to end
  2070.         xor     eax, eax
  2071.         inc        eax
  2072.         CPU_ID                    // Get family/model/stepping/
  2073.                                 //   features
  2074.  
  2075.         mov        cpuff, edx
  2076.  
  2077. end_cpuff:
  2078.         mov        eax, cpuff
  2079.       }
  2080.     }
  2081.  
  2082.     return cpuff;
  2083.  
  2084. } // wincpufeatures()
  2085.  
  2086.  
  2087. /***************************************************************
  2088. * wincpuidext()
  2089. *
  2090. * Inputs: none
  2091. *
  2092. * Returns:
  2093. * AX(15:14) = Reserved (mask these off in the calling code 
  2094. *                before using)
  2095. * AX(13:12) = Processor type (00=Standard OEM CPU, 01=OverDrive,
  2096. *                10=Dual CPU, 11=Reserved)
  2097. * AX(11:8)  = CPU Family (the same 4-bit quantity as wincpuid())
  2098. * AX(7:4)   = CPU Model, if the processor supports the CPUID 
  2099. *                opcode; zero otherwise
  2100. * AX(3:0)   = Stepping #, if the processor supports the CPUID 
  2101. *                opcode; zero otherwise
  2102. *
  2103. *  Note: This function also sets the global variable clone_flag
  2104. ***************************************************************/
  2105.  
  2106. WORD wincpuidext(CString &vendorName) {
  2107.  
  2108.         int i=0;
  2109.         WORD cpu_type=0x0000;
  2110.         WORD cpuidext=0x0000;
  2111.         BYTE vendor_id[]="------------";
  2112.         BYTE intel_id[]="GenuineIntel";
  2113.  
  2114.     if ( wincpuidsupport() ) {
  2115.  
  2116. _asm {      
  2117.  
  2118.         xor     eax, eax        // Set up for CPUID instruction
  2119.         
  2120.         CPU_ID                  // Get and save vendor ID
  2121.  
  2122.         mov     dword ptr vendor_id, ebx
  2123.         mov     dword ptr vendor_id[+4], edx
  2124.         mov     dword ptr vendor_id[+8], ecx
  2125. }
  2126. vendorName = vendor_id;
  2127.  
  2128. for (i=0;i<12;i++)
  2129. {
  2130.     if (!(vendor_id[i]==intel_id[i]))
  2131.         clone_flag = 1;    
  2132. }
  2133.  
  2134. _asm {
  2135.         
  2136.         cmp     eax, 1            // Make sure 1 is valid input 
  2137.                                 //   for CPUID
  2138.         
  2139.         jl      end_cpuidext    // If not, jump to end
  2140.         xor     eax, eax
  2141.         inc        eax
  2142.         CPU_ID                    // Get family/model/stepping/
  2143.                                 //   features
  2144.  
  2145.         mov        cpuidext, ax
  2146.  
  2147. end_cpuidext:
  2148.         mov        ax, cpuidext
  2149.         }
  2150.     }
  2151.     else {
  2152.  
  2153.     cpu_type = wincpuid();        // If CPUID opcode is not
  2154.     cpuidext = cpu_type << 8;    //   supported, put family
  2155.                                 //   value in extensions and
  2156.     }                            //   return
  2157.     
  2158.     return cpuidext;
  2159.  
  2160. } // wincpuidext()
  2161.  
  2162.  
  2163. static struct FREQ_INFO GetBSFCpuSpeed(ulong cycles)
  2164. {
  2165.     // If processor does not support time 
  2166.     //   stamp reading, but is at least a 
  2167.     //   386 or above, utilize method of 
  2168.     //   timing a loop of BSF instructions 
  2169.     //   which take a known number of cycles
  2170.     //   to run on i386(tm), i486(tm), and
  2171.     //   Pentium(R) processors.
  2172.     LARGE_INTEGER t0,t1;            // Variables for High-
  2173.                                     //   Resolution Performance
  2174.                                     //   Counter reads
  2175.  
  2176.     ulong freq  =0;            // Most current frequ. calculation
  2177.  
  2178.     ulong  ticks;                    // Microseconds elapsed 
  2179.                                     //   during test
  2180.     
  2181.     LARGE_INTEGER count_freq;        // High Resolution 
  2182.                                     //   Performance Counter 
  2183.                                     //   frequency
  2184.  
  2185.     int i;                        // Temporary Variable
  2186.  
  2187.     ulong current = 0;          // Variable to store time
  2188.                                     //   elapsed during loop of
  2189.                                     //   of BSF instructions
  2190.  
  2191.     ulong lowest  = ULONG_MAX;    // Since algorithm finds 
  2192.                                     //   the lowest value out of
  2193.                                     //   a set of samplings, 
  2194.                                     //   this variable is set 
  2195.                                     //   intially to the max 
  2196.                                     //   unsigned long value). 
  2197.                                     //   This guarantees that 
  2198.                                     //   the initialized value 
  2199.                                     //   is not later used as 
  2200.                                     //   the least time through 
  2201.                                     //   the loop.
  2202.  
  2203.     struct FREQ_INFO cpu_speed;
  2204.  
  2205.     memset(&cpu_speed, 0x00, sizeof(cpu_speed));
  2206.  
  2207.     if ( !QueryPerformanceFrequency ( &count_freq ) )
  2208.         return cpu_speed;
  2209.  
  2210.     for ( i = 0; i < SAMPLINGS; i++ ) { // Sample Ten times. Can
  2211.                                      //   be increased or 
  2212.                                      //   decreased depending
  2213.                                      //   on accuracy vs. time
  2214.                                      //   requirements
  2215.  
  2216.         QueryPerformanceCounter(&t0);    // Get start time
  2217.  
  2218.             _asm 
  2219.             {
  2220.                 
  2221.                     mov eax, 80000000h    
  2222.                     mov bx, ITERATIONS        
  2223.                                 // Number of consecutive BSF 
  2224.                                 //   instructions to execute. 
  2225.                                 //   Set identical to 
  2226.                                 //   nIterations constant in
  2227.                                 //   speed.h
  2228.                
  2229.                 loop1:    bsf ecx,eax
  2230.        
  2231.                            dec    bx
  2232.                         jnz    loop1
  2233.             }
  2234.                              
  2235.         QueryPerformanceCounter(&t1);    // Get end time
  2236.         current = (ulong) t1.LowPart - (ulong) t0.LowPart;    
  2237.                                 // Number of external ticks is
  2238.                                 //   difference between two
  2239.                                 //   hi-res counter reads.
  2240.  
  2241.         if ( current < lowest )        // Take lowest elapsed
  2242.             lowest = current;        //   time to account
  2243.     }                                //   for some samplings
  2244.                                         //   being interrupted
  2245.                                         //   by other operations 
  2246.          
  2247.     ticks = lowest;
  2248.  
  2249.     // Note that some seemingly arbitrary mulitplies and
  2250.     //   divides are done below. This is to maintain a 
  2251.     //   high level of precision without truncating the 
  2252.     //   most significant data. According to what value 
  2253.     //   ITERATIIONS is set to, these multiplies and
  2254.     //   divides might need to be shifted for optimal
  2255.     //   precision.
  2256.  
  2257.     ticks = ticks * 100000;    
  2258.                         // Convert ticks to hundred
  2259.                         //   thousandths of a tick
  2260.             
  2261.     ticks = ticks / ( count_freq.LowPart/10 );        
  2262.                         // Hundred Thousandths of a 
  2263.                         //   Ticks / ( 10 ticks/second )
  2264.                         //   = microseconds (us)
  2265.         
  2266.     if ( ticks%count_freq.LowPart > count_freq.LowPart/2 )    
  2267.         ticks++;                // Round up if necessary
  2268.             
  2269.     freq = cycles/ticks;        // Cycles / us  = MHz
  2270.  
  2271.     cpu_speed.raw_freq  = freq;
  2272.     if ( cycles%ticks > ticks/2 )
  2273.            freq++;                    // Round up if necessary    
  2274.  
  2275.     cpu_speed.in_cycles = cycles;    // Return variable structure
  2276.     cpu_speed.ex_ticks  = ticks;    //   determined by one of 
  2277.     cpu_speed.norm_freq = freq;
  2278.  
  2279.     return cpu_speed;
  2280. }    
  2281.  
  2282. static struct FREQ_INFO GetRDTSCCpuSpeed()
  2283. {
  2284.     struct FREQ_INFO cpu_speed;
  2285.     LARGE_INTEGER t0,t1;            // Variables for High-
  2286.                                     //   Resolution Performance
  2287.                                     //   Counter reads
  2288.  
  2289.     ulong freq  =0;            // Most current frequ. calculation
  2290.     ulong freq2 =0;            // 2nd most current frequ. calc.
  2291.     ulong freq3 =0;            // 3rd most current frequ. calc.
  2292.     
  2293.     ulong total;            // Sum of previous three frequency
  2294.                             //   calculations
  2295.  
  2296.     int tries=0;            // Number of times a calculation has
  2297.                             //   been made on this call to 
  2298.                             //   cpuspeed
  2299.  
  2300.     ulong  total_cycles=0, cycles;    // Clock cycles elapsed 
  2301.                                     //   during test
  2302.     
  2303.     ulong  stamp0, stamp1;            // Time Stamp Variable 
  2304.                                     //   for beginning and end 
  2305.                                     //   of test
  2306.  
  2307.     ulong  total_ticks=0, ticks;    // Microseconds elapsed 
  2308.                                     //   during test
  2309.     
  2310.     LARGE_INTEGER count_freq;        // High Resolution 
  2311.                                     //   Performance Counter 
  2312.                                     //   frequency
  2313.  
  2314. #ifdef WIN32
  2315.     int iPriority;
  2316.     HANDLE hThread = GetCurrentThread();
  2317. #endif // WIN32;
  2318.  
  2319.     memset(&cpu_speed, 0x00, sizeof(cpu_speed));
  2320.  
  2321.     if ( !QueryPerformanceFrequency ( &count_freq ) )
  2322.         return cpu_speed;
  2323.  
  2324.     // On processors supporting the Read 
  2325.     //   Time Stamp opcode, compare elapsed
  2326.     //   time on the High-Resolution Counter
  2327.     //   with elapsed cycles on the Time 
  2328.     //   Stamp Register.
  2329.     
  2330.     do {            // This do loop runs up to 20 times or
  2331.                        //   until the average of the previous 
  2332.                        //   three calculated frequencies is 
  2333.                        //   within 1 MHz of each of the 
  2334.                        //   individual calculated frequencies. 
  2335.                     //   This resampling increases the 
  2336.                     //   accuracy of the results since
  2337.                     //   outside factors could affect this
  2338.                     //   calculation
  2339.             
  2340.         tries++;        // Increment number of times sampled
  2341.                         //   on this call to cpuspeed
  2342.             
  2343.         freq3 = freq2;    // Shift frequencies back to make
  2344.         freq2 = freq;    //   room for new frequency 
  2345.                         //   measurement
  2346.  
  2347.         QueryPerformanceCounter(&t0);    
  2348.                         // Get high-resolution performance 
  2349.                         //   counter time
  2350.             
  2351.         t1.LowPart = t0.LowPart;        // Set Initial time
  2352.         t1.HighPart = t0.HighPart;
  2353.  
  2354. #ifdef WIN32
  2355.         iPriority = GetThreadPriority(hThread);
  2356.         if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )
  2357.         {
  2358.             SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
  2359.         }
  2360. #endif // WIN32
  2361.  
  2362.            while ( (ulong)t1.LowPart - (ulong)t0.LowPart<50) {      
  2363.                            // Loop until 50 ticks have 
  2364.                            //   passed    since last read of hi-
  2365.                         //     res counter. This accounts for
  2366.                         //   overhead later.
  2367.  
  2368.             QueryPerformanceCounter(&t1);
  2369.  
  2370.             RDTSC;                        // Read Time Stamp
  2371.             _asm {
  2372.                 MOV stamp0, EAX
  2373.             }
  2374.         }
  2375.             
  2376.             
  2377.         t0.LowPart = t1.LowPart;        // Reset Initial 
  2378.         t0.HighPart = t1.HighPart;        //   Time
  2379.  
  2380.            while ((ulong)t1.LowPart-(ulong)t0.LowPart<1000 ) {
  2381.                            // Loop until 1000 ticks have 
  2382.                            //   passed    since last read of hi-
  2383.                            //   res counter. This allows for
  2384.                         //   elapsed time for sampling.
  2385.                
  2386.                 
  2387.                QueryPerformanceCounter(&t1);
  2388.                
  2389.  
  2390.             RDTSC;                        // Read Time Stamp
  2391.             __asm {
  2392.                 MOV stamp1, EAX
  2393.             }
  2394.         }
  2395.  
  2396.             
  2397.  
  2398. #ifdef WIN32
  2399.         // Reset priority
  2400.         if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )
  2401.         {
  2402.             SetThreadPriority(hThread, iPriority);
  2403.         }
  2404. #endif // WIN32
  2405.  
  2406.            cycles = stamp1 - stamp0;    // Number of internal 
  2407.                                     //   clock cycles is 
  2408.                                     //   difference between 
  2409.                                     //   two time stamp 
  2410.                                     //   readings.
  2411.  
  2412.         ticks = (ulong) t1.LowPart - (ulong) t0.LowPart;    
  2413.                                 // Number of external ticks is
  2414.                                 //   difference between two
  2415.                                 //   hi-res counter reads.
  2416.     
  2417.  
  2418.         // Note that some seemingly arbitrary multiplies and
  2419.         //   divides are done below. This is to maintain a 
  2420.         //   high level of precision without truncating the 
  2421.         //   most significant data. According to what value 
  2422.         //   ITERATIONS is set to, these multiplies and
  2423.         //   divides might need to be shifted for optimal
  2424.         //   precision.
  2425.  
  2426.         ticks = ticks * 100000;    
  2427.                             // Convert ticks to hundred
  2428.                             //   thousandths of a tick
  2429.             
  2430.         ticks = ticks / ( count_freq.LowPart/10 );        
  2431.                             // Hundred Thousandths of a 
  2432.                             //   Ticks / ( 10 ticks/second )
  2433.                             //   = microseconds (us)
  2434.  
  2435.         total_ticks += ticks;
  2436.         total_cycles += cycles;
  2437.  
  2438.         if ( ticks%count_freq.LowPart > count_freq.LowPart/2 )
  2439.             ticks++;            // Round up if necessary
  2440.             
  2441.         freq = cycles/ticks;    // Cycles / us  = MHz
  2442.                                                 
  2443.          if ( cycles%ticks > ticks/2 )
  2444.                freq++;                // Round up if necessary
  2445.               
  2446.         total = ( freq + freq2 + freq3 );
  2447.                             // Total last three frequency 
  2448.                             //   calculations
  2449.  
  2450.     } while ( (tries < 3 ) ||         
  2451.               (tries < 20)&&
  2452.               ((abs(int(3 * freq -total)) > 3*TOLERANCE )||
  2453.                (abs(int(3 * freq2-total)) > 3*TOLERANCE )||
  2454.                (abs(int(3 * freq3-total)) > 3*TOLERANCE )));    
  2455.                     // Compare last three calculations to 
  2456.                       //   average of last three calculations.        
  2457.  
  2458.     // Try one more significant digit.
  2459.     freq3 = ( total_cycles * 10 ) / total_ticks;
  2460.     freq2 = ( total_cycles * 100 ) / total_ticks;
  2461.  
  2462.  
  2463.     if ( freq2 - (freq3 * 10) >= ROUND_THRESHOLD )
  2464.         freq3++;
  2465.  
  2466.     cpu_speed.raw_freq = total_cycles / total_ticks;
  2467.     cpu_speed.norm_freq = cpu_speed.raw_freq;
  2468.  
  2469.     freq = cpu_speed.raw_freq * 10;
  2470.     if( (freq3 - freq) >= ROUND_THRESHOLD )
  2471.         cpu_speed.norm_freq++;
  2472.  
  2473.     cpu_speed.ex_ticks = total_ticks;
  2474.     cpu_speed.in_cycles = total_cycles;
  2475.  
  2476.     return cpu_speed;
  2477. }
  2478.  
  2479.  
  2480. //CPU Speed functions
  2481. /***************************************************************
  2482. * CpuSpeed() -- Return the raw clock rate of the host CPU.
  2483. *
  2484. * Inputs:
  2485. *    clocks:        0: Use default value for number of cycles
  2486. *                   per BSF instruction.
  2487. *               -1: Use CMos timer to get cpu speed.
  2488. *               Positive Integer: Use clocks value for number
  2489. *                   of cycles per BSF instruction.
  2490. *
  2491. * Returns:
  2492. *        If error then return all zeroes in FREQ_INFO structure
  2493. *        Else return FREQ_INFO structure containing calculated 
  2494. *       clock frequency, normalized clock frequency, number of 
  2495. *       clock cycles during test sampling, and the number of 
  2496. *       microseconds elapsed during the sampling.
  2497. ***************************************************************/
  2498.  
  2499. struct FREQ_INFO cpuspeed(int clocks) 
  2500. {
  2501.     ulong  cycles;                    // Clock cycles elapsed 
  2502.                                     //   during test
  2503.     
  2504.     ushort processor = wincpuid();    // Family of processor
  2505.  
  2506.  
  2507.     CString vendor;
  2508.     DWORD features = wincpufeatures(vendor);    // Features of Processor
  2509.  
  2510.     int manual=0;            // Specifies whether the user 
  2511.                             //   manually entered the number of
  2512.                             //   cycles for the BSF instruction.
  2513.  
  2514.     struct FREQ_INFO cpu_speed;        // Return structure for
  2515.                                     //   cpuspeed
  2516.  
  2517.     memset(&cpu_speed, 0x00, sizeof(cpu_speed));
  2518.     
  2519.     // Check for manual BSF instruction clock count
  2520.     if (clocks <= 0) {
  2521.         cycles = ITERATIONS * processor_cycles[processor];
  2522.     }
  2523.     else if (0 < clocks && clocks <= MAXCLOCKS)  {
  2524.         cycles = ITERATIONS * clocks;
  2525.         manual = 1;            // Toggle manual control flag.
  2526.                             //   Note that this mode will not
  2527.                             //      work properly with processors
  2528.                             //   which can process multiple
  2529.                             //   BSF instructions at a time.
  2530.                             //   For example, manual mode
  2531.                             //   will not work on a 
  2532.                             //   PentiumPro(R)
  2533.     }
  2534.  
  2535.     if ( ( features&0x00000010 ) && !(manual) ) {                        
  2536.                         // On processors supporting the Read 
  2537.                         //   Time Stamp opcode, compare elapsed
  2538.                         //   time on the High-Resolution Counter
  2539.                         //   with elapsed cycles on the Time 
  2540.                         //   Stamp Register.
  2541.         if ( clocks == 0 )
  2542.             return GetRDTSCCpuSpeed();
  2543.         else
  2544.             return cpu_speed;
  2545.     }
  2546.     else if ( processor >= 3 ) {
  2547.         return GetBSFCpuSpeed(cycles);
  2548.     }
  2549.  
  2550.     return cpu_speed;
  2551.  
  2552. } // cpuspeed()
  2553.  
  2554.  
  2555. // Internal Private Functions //////////////////////////////////
  2556.  
  2557. /***************************************************************
  2558. * check_clone()
  2559. *
  2560. * Inputs: none
  2561. *
  2562. * Returns:
  2563. *   1      if processor is clone (limited detection ability)
  2564. *   0      otherwise
  2565. ***************************************************************/
  2566.  
  2567. static WORD check_clone()
  2568. {
  2569.     short cpu_type=0;
  2570.  
  2571.     _asm 
  2572.         {
  2573.                       MOV AX,5555h    // Check to make sure this
  2574.                     XOR DX,DX        //   is a 32-bit processor
  2575.                     MOV CX,2h
  2576.                     DIV CX            // Perform Division
  2577.                     CLC
  2578.                     JNZ no_clone
  2579.                     JMP clone
  2580.         no_clone:    STC
  2581.         clone:        PUSHF
  2582.                     POP AX          // Get the flags
  2583.                     AND AL,1
  2584.                     XOR AL,1        // AL=0 is probably Intel,
  2585.                                     //   AL=1 is a Clone
  2586.                     
  2587.                     MOV cpu_type, ax
  2588.         }
  2589.     
  2590.     cpu_type = cpu_type & 0x0001;
  2591.     
  2592.     return cpu_type;
  2593.         
  2594. } // check_clone()
  2595.  
  2596. /***************************************************************
  2597. * check_8086()
  2598. *
  2599. * Inputs: none
  2600. *
  2601. * Returns: 
  2602. *   0      if processor 8086
  2603. *   0xffff otherwise
  2604. ***************************************************************/
  2605.  
  2606. static WORD check_8086()
  2607. {
  2608.  
  2609.         WORD cpu_type=0xffff;
  2610.  
  2611. _asm {
  2612.         pushf                   // Push original FLAGS
  2613.         pop     ax              // Get original FLAGS
  2614.         mov     cx, ax          // Save original FLAGS
  2615.         and     ax, 0fffh       // Clear bits 12-15 in FLAGS
  2616.         push    ax              // Save new FLAGS value on stack
  2617.         popf                    // Replace current FLAGS value
  2618.         pushf                   // Get new FLAGS
  2619.         pop     ax              // Store new FLAGS in AX
  2620.         and     ax, 0f000h      // If bits 12-15 are set, then
  2621.         cmp     ax, 0f000h      //   processor is an 8086/8088
  2622.         mov     cpu_type, 0        // Turn on 8086/8088 flag
  2623.         je      end_8086        // Jump if processor is 8086/
  2624.                                 //   8088
  2625.         mov        cpu_type, 0ffffh
  2626. end_8086:
  2627.         push     cx
  2628.         popf
  2629.         mov        ax, cpu_type
  2630.  
  2631.       }
  2632.     
  2633.     return cpu_type;
  2634.  
  2635. } // check_8086()
  2636.  
  2637.  
  2638.  
  2639. /***************************************************************
  2640. * check_80286()
  2641. *
  2642. * Inputs: none
  2643. *
  2644. * Returns:
  2645. *   2      if processor 80286
  2646. *   0xffff otherwise
  2647. ***************************************************************/
  2648.  
  2649. static WORD check_80286()
  2650. {
  2651.  
  2652.         WORD cpu_type=0xffff;
  2653.  
  2654. _asm {
  2655.         pushf
  2656.         pop        cx
  2657.         mov        bx, cx
  2658.         or      cx, 0f000h      // Try to set bits 12-15
  2659.         push    cx              // Save new FLAGS value on stack
  2660.         popf                    // Replace current FLAGS value
  2661.         pushf                   // Get new FLAGS
  2662.         pop     ax              // Store new FLAGS in AX
  2663.         and     ax, 0f000h      // If bits 12-15 are clear
  2664.         
  2665.         mov     cpu_type, 2     // Processor=80286, turn on 
  2666.                                 //   80286 flag
  2667.         
  2668.         jz      end_80286       // If no bits set, processor is 
  2669.                                 //   80286
  2670.         
  2671.         mov        cpu_type, 0ffffh
  2672. end_80286:
  2673.         push    bx
  2674.         popf
  2675.         mov        ax, cpu_type
  2676.  
  2677.       }
  2678.     
  2679.     return cpu_type;
  2680.  
  2681. } // check_80286()
  2682.  
  2683.  
  2684.  
  2685. /***************************************************************
  2686. * check_80386()
  2687. *
  2688. * Inputs: none
  2689. *
  2690. * Returns:
  2691. *   3      if processor 80386
  2692. *   0xffff otherwise
  2693. ***************************************************************/
  2694.  
  2695. static WORD check_80386()
  2696. {
  2697.  
  2698.         WORD cpu_type=0xffff;
  2699.  
  2700. _asm {   
  2701.         mov     bx, sp
  2702.         and        sp, not 3
  2703.         pushfd                    // Push original EFLAGS 
  2704.         pop     eax                // Get original EFLAGS
  2705.         mov     ecx, eax        // Save original EFLAGS
  2706.         xor     eax, 40000h        // Flip AC bit in EFLAGS
  2707.         
  2708.         push    eax             // Save new EFLAGS value on
  2709.                                 //   stack
  2710.         
  2711.         popfd                   // Replace current EFLAGS value
  2712.         pushfd                    // Get new EFLAGS
  2713.         pop     eax             // Store new EFLAGS in EAX
  2714.         
  2715.         xor     eax, ecx        // Can't toggle AC bit, 
  2716.                                 //   processor=80386
  2717.         
  2718.         mov     cpu_type, 3        // Turn on 80386 processor flag
  2719.         jz      end_80386        // Jump if 80386 processor
  2720.         mov        cpu_type, 0ffffh
  2721. end_80386:
  2722.         push    ecx
  2723.         popfd
  2724.         mov        sp, bx
  2725.         mov        ax, cpu_type
  2726.         and        eax, 0000ffffh
  2727.       }
  2728.  
  2729.     return cpu_type;
  2730.  
  2731. } // check_80386()
  2732.  
  2733.  
  2734.  
  2735. /***************************************************************
  2736. * check_IDProc()
  2737. *
  2738. * Inputs: none
  2739. *
  2740. * Returns:
  2741. *  CPU Family (i.e. 4 if Intel 486, 5 if Pentium(R) Processor)
  2742. *
  2743. *  Note: This function also sets the global variable clone_flag
  2744. ***************************************************************/
  2745.  
  2746. static WORD check_IDProc() {
  2747.  
  2748.         int i=0;
  2749.         WORD cpu_type=0xffff;
  2750.         BYTE stepping=0;
  2751.         BYTE model=0;
  2752.         BYTE vendor_id[]="------------";
  2753.         BYTE intel_id[]="GenuineIntel";
  2754.  
  2755. _asm {      
  2756.  
  2757.         xor     eax, eax        // Set up for CPUID instruction
  2758.         
  2759.         CPU_ID                  // Get and save vendor ID
  2760.  
  2761.         mov     dword ptr vendor_id, ebx
  2762.         mov     dword ptr vendor_id[+4], edx
  2763.         mov     dword ptr vendor_id[+8], ecx
  2764. }
  2765.  
  2766. for (i=0;i<12;i++)
  2767. {
  2768.     if (!(vendor_id[i]==intel_id[i]))
  2769.         clone_flag = 1;    
  2770. }
  2771.  
  2772. _asm {
  2773.  
  2774.         cmp     eax, 1            // Make sure 1 is valid input 
  2775.                                 //   for CPUID
  2776.         
  2777.         jl      end_IDProc        // If not, jump to end
  2778.         xor     eax, eax
  2779.         inc        eax
  2780.         CPU_ID                    // Get family/model/stepping/
  2781.                                 //   features
  2782.  
  2783.         mov     stepping, al
  2784.         and        stepping, 0x0f //0fh
  2785.         
  2786.         and     al, 0f0h
  2787.         shr        al, 4
  2788.         mov     model, al
  2789.         
  2790.         and        eax, 0f00h
  2791.         shr     eax, 8            // Isolate family
  2792.         and        eax, 0fh
  2793.         mov     cpu_type, ax    // Set _cpu_type with family
  2794.  
  2795. end_IDProc:
  2796.         mov        ax, cpu_type
  2797.       }
  2798.     
  2799.     return cpu_type;
  2800.  
  2801. } // Check_IDProc()
  2802.  
  2803.  
  2804.