sccls.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 18k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. #define  DONT_USE_ATL
  2. #include "priv.h"
  3. #include "sccls.h"
  4. #include <ntverp.h>
  5. #include <shdguid.h>
  6. #include <shguidp.h>                // for CLSID_CDocObjectFolder
  7. #include <shlobj.h>                 // for CLSID_ACLMRU
  8. #include <schedule.h>
  9. #include "shbrows2.h"               // CWinInetNotify_szWindowClass
  10. #include "desktop.h"                // DESKTOPPROXYCLASS
  11. #include "mluisupp.h"
  12. STDAPI_(void) InitURLIDs(UINT uPlatform);       // from shdocfl.cpp
  13. STDAPI SHIsThereASystemScheduler(void);         // from schedule.cpp
  14. STDAPI SHFreeSystemScheduler(void);
  15. LONG                g_cRefThisDll = 0;      // per-instance
  16. CRITICAL_SECTION    g_csDll = {0};          // per-instance
  17. HINSTANCE           g_hinst = NULL;
  18. HANDLE              g_hMutexHistory = NULL;
  19. BOOL g_fNashInNewProcess = FALSE;           // Are we running in a separate process
  20. BOOL g_fRunningOnNT = FALSE;
  21. BOOL g_bRunOnNT5 = FALSE;
  22. BOOL g_bRunOnMemphis = FALSE;
  23. BOOL g_fRunOnFE = FALSE;
  24. DWORD g_dwStopWatchMode = 0;                // Shell perf automation
  25. HKEY g_hkeyExplorer = NULL;                 // for SHGetExplorerHKey() in util.cpp
  26. HANDLE g_hCabStateChange = NULL;
  27. // Is Mirroring enabled
  28. BOOL g_bMirroredOS = FALSE;
  29. HPALETTE g_hpalHalftone = NULL;
  30. #ifdef UNIX
  31. EXTERN_C const GUID     CLSID_MsgBand;
  32. STDAPI CMsgBand_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi);
  33. #endif
  34. extern PZONEICONNAMECACHE g_pZoneIconNameCache;
  35. extern DWORD g_dwZoneCount;
  36. //
  37. // This array holds information needed for ClassFacory.
  38. // OLEMISC_ flags are used by shembed and shocx.
  39. //
  40. // BUGBUG: this table should be ordered in most-to-least used order
  41. //
  42. CF_TABLE_BEGIN(g_ObjectInfo)
  43.     CF_TABLE_ENTRY( &CLSID_InternetToolbar,         CInternetToolbar_CreateInstance,
  44.         COCREATEONLY),
  45.     CF_TABLE_ENTRY( &CLSID_BrandBand,               CBrandBand_CreateInstance,
  46.         COCREATEONLY),
  47.     CF_TABLE_ENTRY( &CLSID_MenuBand,                CMenuBand_CreateInstance,
  48.         COCREATEONLY),
  49.     CF_TABLE_ENTRY( &CLSID_MenuBandSite,            CMenuBandSite_CreateInstance,
  50.         COCREATEONLY),
  51.     CF_TABLE_ENTRY( &CLSID_MenuDeskBar,                CMenuDeskBar_CreateInstance,
  52.         COCREATEONLY),
  53.     CF_TABLE_ENTRY( &CLSID_QuickLinks,              CQuickLinks_CreateInstance,
  54.         COCREATEONLY),
  55.     CF_TABLE_ENTRY( &CLSID_AugmentedShellFolder,    CAugmentedISF_CreateInstance,
  56.         COCREATEONLY),
  57.     CF_TABLE_ENTRY( &CLSID_AugmentedShellFolder2,    CAugmentedMergeISF_CreateInstance,
  58.         COCREATEONLY),
  59.     CF_TABLE_ENTRY( &CLSID_AddressBand,             CAddressBand_CreateInstance,
  60.         COCREATEONLY),
  61.     CF_TABLE_ENTRY( &CLSID_AddressEditBox,             CAddressEditBox_CreateInstance,
  62.         COCREATEONLY),
  63.     CF_TABLE_ENTRY( &CLSID_BandProxy,               CBandProxy_CreateInstance,
  64.         COCREATEONLY),
  65.     CF_TABLE_ENTRY( &CLSID_ISFBand,                 CISFBand_CreateInstance,
  66.         COCREATEONLY),
  67.     CF_TABLE_ENTRY_NOFLAGS( &CLSID_RebarBandSite,           CBandSite_CreateInstance,
  68.         COCREATEONLY_NOFLAGS, OIF_ALLOWAGGREGATION),
  69.     CF_TABLE_ENTRY( &CLSID_DeskBarApp,              CDeskBarApp_CreateInstance,
  70.         COCREATEONLY),
  71.     CF_TABLE_ENTRY( &CLSID_DeskBar,                 CDeskBar_CreateInstance,
  72.         COCREATEONLY),
  73.     CF_TABLE_ENTRY( &CLSID_AutoComplete,            CAutoComplete_CreateInstance,
  74.         COCREATEONLY),
  75. #ifdef ENABLE_CCHANNELBAND
  76.     CF_TABLE_ENTRY( &CLSID_ChannelBand,             CChannelBand_CreateInstance,
  77.         COCREATEONLY),
  78. #endif // ENABLE_CCHANNELBAND
  79. #ifdef UNIX
  80.     CF_TABLE_ENTRY( &CLSID_MsgBand ,                CMsgBand_CreateInstance,
  81.         COCREATEONLY),
  82. #else
  83.     CF_TABLE_ENTRY( &CLSID_ExplorerBand,            CExplorerBand_CreateInstance,
  84.         COCREATEONLY),
  85. #endif
  86.     CF_TABLE_ENTRY( &CLSID_ACLHistory,              CACLHistory_CreateInstance,
  87.         COCREATEONLY),
  88.     CF_TABLE_ENTRY( &CLSID_ACListISF,               CACLIShellFolder_CreateInstance,
  89.         COCREATEONLY),
  90.     CF_TABLE_ENTRY( &CLSID_ACLMRU,                  CACLMRU_CreateInstance,
  91.         COCREATEONLY),
  92.     CF_TABLE_ENTRY( &CLSID_ACLMulti,                CACLMulti_CreateInstance,
  93.         COCREATEONLY),
  94.     CF_TABLE_ENTRY_NOFLAGS( &CLSID_CCommonBrowser,           CCommonBrowser_CreateInstance,
  95.         COCREATEONLY_NOFLAGS, OIF_ALLOWAGGREGATION),
  96.     CF_TABLE_ENTRY( &CLSID_CDockingBarPropertyBag,   CDockingBarPropertyBag_CreateInstance,
  97.         COCREATEONLY),
  98.     CF_TABLE_ENTRY( &CLSID_CRegTreeOptions,          CRegTreeOptions_CreateInstance,
  99.         COCREATEONLY),
  100.     CF_TABLE_ENTRY( &CLSID_Thumbnail,                CThumbnail_CreateInstance,
  101.         COCREATEONLY),
  102.     CF_TABLE_ENTRY( &CLSID_BrowserBand,             CBrowserBand_CreateInstance,
  103.         COCREATEONLY),
  104.     CF_TABLE_ENTRY( &CLSID_SearchBand,              CSearchBand_CreateInstance,
  105.         COCREATEONLY),
  106.     CF_TABLE_ENTRY( &CLSID_CommBand,                CCommBand_CreateInstance,
  107.         COCREATEONLY),
  108.     CF_TABLE_ENTRY( &CLSID_BandSiteMenu,            CBandSiteMenu_CreateInstance,
  109.         COCREATEONLY),
  110.     CF_TABLE_ENTRY( &CLSID_ComCatCacheTask,           CComCatCacheTask_CreateInstance,
  111.         COCREATEONLY),
  112.     CF_TABLE_ENTRY( &CLSID_ComCatConditionalCacheTask,CComCatConditionalCacheTask_CreateInstance,
  113.         COCREATEONLY),
  114.     CF_TABLE_ENTRY( &CLSID_ImgCtxThumbnailExtractor,  CImgCtxThumb_CreateInstance,
  115.         COCREATEONLY),
  116.     CF_TABLE_ENTRY( &CLSID_ImageListCache,            CImageListCache_CreateInstance,
  117.         COCREATEONLY),
  118.     CF_TABLE_ENTRY( &CLSID_ShellTaskScheduler,        CShellTaskScheduler_CreateInstance,
  119.         COCREATEONLY),
  120.     CF_TABLE_ENTRY( &CLSID_SharedTaskScheduler,       CSharedTaskScheduler_CreateInstance,
  121.         COCREATEONLY),
  122.     CF_TABLE_ENTRY( &CLSID_BrowseuiPreloader,         CBitmapPreload_CreateInstance,
  123.         COCREATEONLY),
  124.     CF_TABLE_ENTRY( &CLSID_ShellSearchExt,            CShellSearchExt_CreateInstance,
  125.         COCREATEONLY),
  126.     CF_TABLE_ENTRY( &CLSID_WebSearchExt,              CWebSearchExt_CreateInstance,
  127.         COCREATEONLY),
  128.     CF_TABLE_ENTRY( &CLSID_OrderListExport,           COrderList_CreateInstance,
  129.         COCREATEONLY),
  130.     CF_TABLE_ENTRY( &CLSID_UserAssist,                CUserAssist_CreateInstance,
  131.         COCREATEONLY),
  132.     CF_TABLE_ENTRY( &CLSID_GlobalFolderSettings,      CGlobalFolderSettings_CreateInstance,
  133.         COCREATEONLY),
  134.     CF_TABLE_ENTRY( &CLSID_ProgressDialog,            CProgressDialog_CreateInstance,
  135.         COCREATEONLY),
  136.     CF_TABLE_ENTRY( &CLSID_TrackShellMenu,            CTrackShellMenu_CreateInstance,
  137.         COCREATEONLY),
  138. CF_TABLE_END(g_ObjectInfo)
  139. // constructor for CObjectInfo.
  140. CObjectInfo::CObjectInfo(CLSID const* pclsidin, LPFNCREATEOBJINSTANCE pfnCreatein, IID const* piidIn,
  141.                          IID const* piidEventsIn, long lVersionIn, DWORD dwOleMiscFlagsIn,
  142.                          DWORD dwClassFactFlagsIn)
  143. {
  144.     pclsid            = pclsidin;
  145.     pfnCreateInstance = pfnCreatein;
  146.     piid              = piidIn;
  147.     piidEvents        = piidEventsIn;
  148.     lVersion          = lVersionIn;
  149.     dwOleMiscFlags    = dwOleMiscFlagsIn;
  150.     dwClassFactFlags  = dwClassFactFlagsIn;
  151. }
  152. // static class factory (no allocs!)
  153. STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, void **ppvObj)
  154. {
  155.     if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
  156.     {
  157.         *ppvObj = (void *)GET_ICLASSFACTORY(this);
  158.         DllAddRef();
  159.         return NOERROR;
  160.     }
  161.     *ppvObj = NULL;
  162.     return E_NOINTERFACE;
  163. }
  164. STDMETHODIMP_(ULONG) CClassFactory::AddRef()
  165. {
  166.     DllAddRef();
  167.     return 2;
  168. }
  169. STDMETHODIMP_(ULONG) CClassFactory::Release()
  170. {
  171.     DllRelease();
  172.     return 1;
  173. }
  174. STDMETHODIMP CClassFactory::CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
  175. {
  176.     *ppv = NULL;
  177.     if (punkOuter && !IsEqualIID(riid, IID_IUnknown))
  178.     {
  179.         // It is technically illegal to aggregate an object and request
  180.         // any interface other than IUnknown. Enforce this.
  181.         //
  182.         return CLASS_E_NOAGGREGATION;
  183.     }
  184.     else
  185.     {
  186.         LPOBJECTINFO pthisobj = (LPOBJECTINFO)this;
  187.         if (punkOuter && !(pthisobj->dwClassFactFlags & OIF_ALLOWAGGREGATION))
  188.             return CLASS_E_NOAGGREGATION;
  189.         IUnknown *punk;
  190.         HRESULT hres = pthisobj->pfnCreateInstance(punkOuter, &punk, pthisobj);
  191.         if (SUCCEEDED(hres))
  192.         {
  193.             hres = punk->QueryInterface(riid, ppv);
  194.             punk->Release();
  195.         }
  196.         ASSERT(FAILED(hres) ? *ppv == NULL : TRUE);
  197.         return hres;
  198.     }
  199. }
  200. STDMETHODIMP CClassFactory::LockServer(BOOL fLock)
  201. {
  202.     if (fLock)
  203.         DllAddRef();
  204.     else
  205.         DllRelease();
  206.     TraceMsg(DM_TRACE, "sccls: LockServer(%s) to %d", fLock ? TEXT("LOCK") : TEXT("UNLOCK"), g_cRefThisDll);
  207.     return S_OK;
  208. }
  209. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
  210. {
  211.     TraceMsg(TF_SHDLIFE, "DllGetClassObject called with riid=%x (%x)", riid, &riid);
  212.     if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
  213.     {
  214.         for (LPCOBJECTINFO pcls = g_ObjectInfo; pcls->pclsid; pcls++)
  215.         {
  216.             if (IsEqualGUID(rclsid, *(pcls->pclsid)))
  217.             {
  218.                 *ppv = (void*)pcls;
  219.                 DllAddRef();        // class factory holds DLL ref count
  220.                 return NOERROR;
  221.             }
  222.         }
  223. #ifdef ATL_ENABLED
  224.         // Try the ATL class factory
  225.         if (SUCCEEDED(AtlGetClassObject(rclsid, riid, ppv)))
  226.             return NOERROR;
  227. #endif
  228.     }
  229.     *ppv = NULL;
  230.     return CLASS_E_CLASSNOTAVAILABLE;
  231. }
  232. STDAPI DllCanUnloadNow(void)
  233. {
  234. #ifndef UNIX
  235.     // special case for the system scheduler we hang onto
  236.     if ( g_cRefThisDll == 1 && SHIsThereASystemScheduler() == S_OK )
  237.     {
  238.         // this will drop the ref count by one to zero....
  239.         SHFreeSystemScheduler();
  240.     }
  241. #ifdef ATL_ENABLED
  242.     if (0 != g_cRefThisDll || 0 != AtlGetLockCount())
  243.         return S_FALSE;
  244. #else
  245.     if (0 != g_cRefThisDll)
  246.         return S_FALSE;
  247. #endif
  248. #else
  249.     if (g_cRefThisDll)
  250.         return S_FALSE;
  251. #endif
  252.     TraceMsg(DM_TRACE, "DllCanUnloadNow returning S_OK (bye, bye...)");
  253.     return S_OK;
  254. }
  255. void DestroyZoneIconNameCache(void)
  256. {
  257.     if (g_pZoneIconNameCache)
  258.     {
  259.         PZONEICONNAMECACHE pzinc = g_pZoneIconNameCache;
  260.         for(DWORD i = 0; i < g_dwZoneCount; i++)
  261.         {
  262.             if (pzinc->hiconZones)
  263.                 DestroyIcon((HICON)pzinc->hiconZones);
  264.             if (pzinc->pszZonesName)
  265.                 LocalFree(pzinc->pszZonesName);
  266.             pzinc++;
  267.         }
  268.         LocalFree(g_pZoneIconNameCache);
  269.         g_pZoneIconNameCache = NULL;
  270.     }
  271. }
  272. // DllGetVersion
  273. //
  274. // All we have to do is declare this puppy and CCDllGetVersion does the rest
  275. //
  276. DLLVER_SINGLEBINARY(VER_PRODUCTVERSION_DW, VER_PRODUCTBUILD_QFE);
  277. UINT g_msgMSWheel;
  278. #ifdef DEBUG
  279. EXTERN_C DWORD g_TlsMem = 0xffffffff;
  280. #endif
  281. // imports from isfband.cpp
  282. STDAPI_(void) CLogoBase_Initialize( void );
  283. STDAPI_(void) CLogoBase_Cleanup( void );
  284. //
  285. //  Table of all window classes we register so we can unregister them
  286. //  at DLL unload.
  287. //
  288. const LPCTSTR c_rgszClasses[] = {
  289.     TEXT("BaseBar"),                // basebar.cpp
  290.     TEXT("MenuSite"),               // menusite.cpp
  291.     c_szOTClass,                    // onetree.cpp
  292.     DESKTOPPROXYCLASS,              // proxy.cpp
  293.     c_szExploreClass,               // shbrows2.cpp
  294.     c_szIExploreClass,              // shbrows2.cpp
  295.     c_szCabinetClass,               // shbrows2.cpp
  296.     c_szAutoSuggestClass,           // autocomp.cpp
  297. };
  298. //
  299. //  Since we are single-binary, we have to play it safe and do
  300. //  this cleanup (needed only on NT, but harmless on Win95).
  301. //
  302. #define UnregisterWindowClasses() 
  303.     SHUnregisterClasses(HINST_THISDLL, c_rgszClasses, ARRAYSIZE(c_rgszClasses))
  304. void InitNFCtl()
  305. {
  306.     INITCOMMONCONTROLSEX icc;
  307.     icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
  308.     icc.dwICC = ICC_NATIVEFNTCTL_CLASS;
  309.     InitCommonControlsEx(&icc);
  310. }
  311. const LPCTSTR s_aryExplorerFileName[] =
  312. {
  313.     TEXT("iexplore.exe"),
  314. };
  315. BOOL IsRootExeExplorer(void)
  316. {
  317.     TCHAR szApp[MAX_PATH];
  318.     LPCTSTR pszApp;
  319.     GetModuleFileName(NULL, szApp, ARRAYSIZE(szApp));
  320.     pszApp = PathFindFileName(szApp);
  321.     if (pszApp)
  322.     {
  323.         for (int i = 0; i < ARRAYSIZE(s_aryExplorerFileName); i++)
  324.         {
  325.             if (!lstrcmpi(pszApp, s_aryExplorerFileName[i]))
  326.                 return TRUE;
  327.         }
  328.     }
  329.     return FALSE;
  330. }
  331. #if defined(MAINWIN)
  332. #define LibMain browseui_DllMain
  333. // IEUNIX - This function  should be moved to some file used to create
  334. // shdocvw.dll. While compiling for DLLs mainsoft will #define DllMain
  335. // to the appropriate function being called in generated *_init.c
  336. #endif
  337. // ccover wants to link to c runtime libs, so we need to rename LibMain to DllMain
  338. #if defined(CCOVER)
  339. #define LibMain DllMain
  340. #endif
  341. STDAPI_(BOOL) LibMain(HINSTANCE hDll, DWORD dwReason, void *lpReserved)
  342. {
  343.     if (dwReason == DLL_PROCESS_ATTACH)
  344.     {
  345. #ifdef ATL_ENABLED
  346.         AtlInit(hDll);
  347. #endif
  348.         DisableThreadLibraryCalls(hDll);    // perf
  349.         g_hinst = hDll;
  350.         InitializeCriticalSection(&g_csDll);
  351.         g_msgMSWheel = RegisterWindowMessage(TEXT("MSWHEEL_ROLLMSG"));
  352.         MLLoadResources(g_hinst, TEXT("browselc.dll"));
  353.         if (IsRootExeExplorer())
  354.             InitMUILanguage(MLGetUILanguage());
  355.         
  356.         // Don't put it under #ifdef DEBUG
  357.         CcshellGetDebugFlags();
  358. #ifdef DEBUG
  359.         g_TlsMem = TlsAlloc();
  360.         if (IsFlagSet(g_dwBreakFlags, BF_ONLOADED))
  361.         {
  362.             TraceMsg(TF_ALWAYS, "SHDOCVW.DLL has just loaded");
  363.             DEBUG_BREAK;
  364.         }
  365. #endif
  366.         g_fRunningOnNT = IsOS(OS_NT);
  367.         if (g_fRunningOnNT)
  368.             g_bRunOnNT5 = IsOS(OS_NT5);
  369.         else
  370.             g_bRunOnMemphis = IsOS(OS_MEMPHIS);
  371.         g_fRunOnFE = GetSystemMetrics(SM_DBCSENABLED);
  372.         DetectRegisterNotify();
  373.         //
  374.         // Check if the mirroring APIs exist on the current
  375.         // platform.
  376.         //
  377.         g_bMirroredOS = IS_MIRRORING_ENABLED();
  378.         InitNFCtl();
  379.         // See if perfmode is enabled
  380.         g_dwStopWatchMode = StopWatchMode();
  381.         // Cache a palette handle for use throughout shdocvw
  382.         g_hpalHalftone = SHCreateShellPalette( NULL );
  383.         CLogoBase_Initialize( );
  384.     }
  385.     else if (dwReason == DLL_PROCESS_DETACH)
  386.     {
  387. #ifdef ATL_ENABLED
  388.         AtlTerm();
  389. #endif
  390.         CBrandBand_CleanUp();
  391.         CInternetToolbar_CleanUp();
  392.         CUserAssist_CleanUp(dwReason, lpReserved);
  393.         CLogoBase_Cleanup();
  394.         // let go of the resource DLL...
  395.         MLFreeResources(g_hinst);
  396.         ENTERCRITICAL;
  397.         DESTROY_OBJ_WITH_HANDLE(g_hpalHalftone, DeletePalette);
  398.         DESTROY_OBJ_WITH_HANDLE(g_hkeyExplorer, RegCloseKey);
  399.         DESTROY_OBJ_WITH_HANDLE(g_hCabStateChange, SHGlobalCounterDestroy);
  400.         DESTROY_OBJ_WITH_HANDLE(g_hMutexHistory, CloseHandle);
  401.         DestroyZoneIconNameCache();
  402.         UnregisterWindowClasses();
  403.         LEAVECRITICAL;
  404.         DeleteCriticalSection(&g_csDll);
  405.     }
  406.     return TRUE;
  407. }
  408. STDAPI_(void) DllAddRef(void)
  409. {
  410.     InterlockedIncrement(&g_cRefThisDll);
  411.     ASSERT(g_cRefThisDll < 1000);   // reasonable upper limit
  412. }
  413. STDAPI_(void) DllRelease(void)
  414. {
  415.     LONG lVal = InterlockedDecrement(&g_cRefThisDll);
  416.     ASSERT(g_cRefThisDll >= 0);      // don't underflow
  417. }
  418. // IEUNIX
  419. // CoCreateInstance is #defined as IECreateInstance #ifdef __cplusplus,
  420. // so I #undef it  here to prevent the recursive call.
  421. // On Windows it works, because this file is C file.
  422. #ifdef CoCreateInstance
  423. #undef CoCreateInstance
  424. #endif
  425. HRESULT IECreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
  426.                     DWORD dwClsContext, REFIID riid, LPVOID FAR* ppv)
  427. {
  428.     LPCOBJECTINFO pcls;
  429. #ifndef NO_MARSHALLING
  430.     if (dwClsContext == CLSCTX_INPROC_SERVER) {
  431. #else
  432.     if (dwClsContext & CLSCTX_INPROC_SERVER) {
  433. #endif
  434.         for (pcls = g_ObjectInfo; pcls->pclsid; pcls++)
  435.         {
  436.             // Note that we do pointer comparison (instead of IsEuqalGUID)
  437.             if (&rclsid == pcls->pclsid)
  438.             {
  439.                 // const -> non-const expclit casting (this is OK)
  440.                 IClassFactory* pcf = GET_ICLASSFACTORY(pcls);
  441.                 return pcf->CreateInstance(pUnkOuter, riid, ppv);
  442.             }
  443.         }
  444.     }
  445.     return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv);
  446. }
  447. #ifdef DEBUG
  448. //
  449. //  In DEBUG, make sure every class we register lives in the c_rgszClasses
  450. //  table so we can clean up properly at DLL unload.  NT does not automatically
  451. //  unregister classes when a DLL unloads, so we have to do it manually.
  452. //
  453. STDAPI_(BOOL) WINAPI SHRegisterClassD(CONST WNDCLASS *pwc)
  454. {
  455.     int i;
  456.     for (i = 0; i < ARRAYSIZE(c_rgszClasses); i++) {
  457.         if (lstrcmpi(c_rgszClasses[i], pwc->lpszClassName) == 0) {
  458.             return RealSHRegisterClass(pwc);
  459.         }
  460.     }
  461.     AssertMsg(0, TEXT("Class %s needs to be added to the c_rgszClasses list"), pwc->lpszClassName);
  462.     return 0;
  463. }
  464. STDAPI_(ATOM) WINAPI RegisterClassD(CONST WNDCLASS *pwc)
  465. {
  466.     int i;
  467.     for (i = 0; i < ARRAYSIZE(c_rgszClasses); i++) {
  468.         if (lstrcmpi(c_rgszClasses[i], pwc->lpszClassName) == 0) {
  469.             return RealRegisterClass(pwc);
  470.         }
  471.     }
  472.     AssertMsg(0, TEXT("Class %s needs to be added to the c_rgszClasses list"), pwc->lpszClassName);
  473.     return 0;
  474. }
  475. //
  476. //  In DEBUG, send FindWindow through a wrapper that ensures that the
  477. //  critical section is not taken.  FindWindow'ing for a window title
  478. //  sends inter-thread WM_GETTEXT messages, which is not obvious.
  479. //
  480. STDAPI_(HWND) FindWindowD(LPCTSTR lpClassName, LPCTSTR lpWindowName)
  481. {
  482.     return FindWindowExD(NULL, NULL, lpClassName, lpWindowName);
  483. }
  484. STDAPI_(HWND) FindWindowExD(HWND hwndParent, HWND hwndChildAfter, LPCTSTR lpClassName, LPCTSTR lpWindowName)
  485. {
  486.     if (lpWindowName) {
  487.         ASSERTNONCRITICAL;
  488.     }
  489.     return RealFindWindowEx(hwndParent, hwndChildAfter, lpClassName, lpWindowName);
  490. }
  491. #endif // DEBUG