init.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 15k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. #include "shellprv.h"
  2. #pragma  hdrstop
  3. #include "copy.h"
  4. #include "ovrlaymn.h"
  5. #include "drives.h"
  6. #include "unicppadmovr2.h"
  7. void FreeExtractIconInfo(int);
  8. void DAD_ThreadDetach(void);
  9. void DAD_ProcessDetach(void);
  10. void TaskMem_MakeInvalid(void);
  11. void UltRoot_Term(void);
  12. void NetRoot_Terminate(void);
  13. void FlushRunDlgMRU(void);
  14. STDAPI_(BOOL) ATL_DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/);
  15. // from mtpt.cpp
  16. STDAPI_(void) CMtPt_FinalCleanUp();
  17. STDAPI_(void) CMtPt_Initialize();
  18. STDAPI_(void) CMtPt_FakeVolatileKeys();
  19. // from rgsprtc.cpp
  20. STDAPI_(void) CRegSupportCached_RSEnableKeyCaching(BOOL fEnable);
  21. // Global data
  22. BOOL g_bMirroredOS = FALSE;         // Is Mirroring enabled 
  23. BOOL g_bBiDiPlatform = FALSE;       // Is DATE_LTRREADING flag supported by GetDateFormat() API?   
  24. #ifdef WINDOWS_ME
  25. // This is needed for BiDi localized win95 RTL stuff
  26. BOOL g_bBiDiW95Loc = FALSE;
  27. #endif // WINDOWS_ME
  28. HINSTANCE g_hinst = NULL;
  29. extern HANDLE g_hCounter;   // Global count of mods to Special Folder cache.
  30. extern HANDLE g_hRestrictions ; // Global count of mods to restriction cache.
  31. extern HANDLE g_hSettings;  // global count of mods to shellsettings cache
  32. HKEY g_hkcrCLSID = NULL;        // HKEY_CLASSES_ROOTCLSID
  33. HKEY g_hklmExplorer = NULL;     // caching for HKEY_LOCAL_MACHINE...Explorer
  34. #ifdef DEBUG
  35. BOOL  g_bInDllEntry = FALSE;
  36. #endif
  37. #pragma data_seg(DATASEG_SHARED)
  38. // evil global global data on Win95 only. on NT these are regular per process
  39. LONG g_cProcesses = 0;
  40. CRITICAL_SECTION g_csDll = {0};
  41. CRITICAL_SECTION g_csPrinters = {0};
  42. // these will always be zero
  43. const LARGE_INTEGER g_li0 = {0};
  44. const ULARGE_INTEGER g_uli0 = {0};
  45. #ifdef WINNT
  46. BOOL g_bRunOnNT5 = FALSE;
  47. #else
  48. BOOL g_bRunOnMemphis = FALSE;
  49. #endif
  50. #pragma data_seg()
  51. #ifdef DEBUG
  52. // Undefine what shlwapi.h defined so our ordinal asserts map correctly
  53. #undef PathAddBackslash 
  54. WINSHELLAPI LPTSTR WINAPI PathAddBackslash(LPTSTR lpszPath);
  55. #undef PathMatchSpec
  56. WINSHELLAPI BOOL  WINAPI PathMatchSpec(LPCTSTR pszFile, LPCTSTR pszSpec);
  57. #endif
  58. BOOL _ProcessAttach(HINSTANCE hDll)
  59. {
  60.     g_hinst = hDll;
  61.     g_uCodePage = GetACP();
  62. #ifdef WINNT
  63.     InitializeCriticalSection(&g_csDll);
  64.     InitializeCriticalSection(&g_csPrinters);
  65. #else
  66.     // these are in global global data, thus we need the "Re" version of these APIs
  67.     ReinitializeCriticalSection(&g_csPrinters);
  68.     ReinitializeCriticalSection(&g_csDll);
  69. #endif
  70.     // Initialize the MountPoint stuff
  71.     CMtPt_Initialize();
  72.     // We need to disable HKEY caching for classes using CRegSupportCached in
  73.     // winlogon since it does not get unloaded.  This must alos apply to the other
  74.     // services loading shell32.dllNot being unloaded the _ProcessDetach
  75.     // never gets called for shell32, and we never release the cached HKEYs.  This
  76.     // prevents the user hives from being unloaded.  SO we'll enable caching only
  77.     // for Explorer.exe.  (stephstm, 08/20/99)
  78.     //
  79.     {
  80.         TCHAR  szModulePath[MAX_PATH];
  81.         LPTSTR pszModuleName;
  82.         BOOL fEnable = FALSE;
  83.         GetModuleFileName(GetModuleHandle(NULL), szModulePath, ARRAYSIZE(szModulePath));
  84.         pszModuleName = PathFindFileName(szModulePath);
  85.         if (pszModuleName)
  86.         {
  87.             // Is this winlogon?
  88.             if (!lstrcmpi(TEXT("explorer.exe"), pszModuleName))
  89.             {
  90.                 // No
  91.                 fEnable = TRUE;
  92.             }
  93.         }
  94.     
  95.         CRegSupportCached_RSEnableKeyCaching(fEnable);
  96.     }
  97.     //
  98.     // Check if the mirroring APIs exist on the current
  99.     // platform.
  100.     //
  101.     g_bMirroredOS = IS_MIRRORING_ENABLED();
  102. #ifdef WINDOWS_ME
  103.     //
  104.     // Check to see if running on BiDi localized Win95
  105.     //
  106.     g_bBiDiW95Loc = IsBiDiLocalizedWin95(FALSE);
  107. #endif // WINDOWS_ME
  108.     // globally useful registry keys
  109.     RegOpenKey(HKEY_CLASSES_ROOT, c_szCLSID, &g_hkcrCLSID);
  110.     RegCreateKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_EXPLORER, &g_hklmExplorer);
  111.     InterlockedIncrement(&g_cProcesses);
  112. #ifdef WINNT
  113.     g_bRunOnNT5     = IsOS(OS_NT5);
  114.     g_bBiDiPlatform =  BOOLFROMPTR(GetModuleHandle(TEXT("LPK.DLL")));
  115. #else
  116.     g_bRunOnMemphis = IsOS(OS_MEMPHIS);
  117.     g_bBiDiPlatform = ((g_uCodePage == CP_ARABIC) || (g_uCodePage == CP_HEBREW));
  118. #endif
  119. #ifdef DEBUG
  120. #define DEREFMACRO(x) x
  121. #define ValidateORD(_name) ASSERT( _name == (LPVOID)GetProcAddress(hDll, (LPSTR)MAKEINTRESOURCE(DEREFMACRO(_name##ORD))) )
  122.     if (g_cProcesses==1)        // no need to be in critical section (just debug)
  123.     {
  124.         ValidateORD(SHValidateUNC);
  125.         ValidateORD(SHChangeNotifyRegister);
  126.         ValidateORD(SHChangeNotifyDeregister);
  127.         ValidateORD(OleStrToStrN);
  128.         ValidateORD(SHCloneSpecialIDList);
  129.         ASSERT(DllGetClassObject==(LPVOID)GetProcAddress(hDll,(LPSTR)MAKEINTRESOURCE(SHDllGetClassObjectORD)));
  130.         ValidateORD(SHLogILFromFSIL);
  131.         ValidateORD(SHMapPIDLToSystemImageListIndex);
  132.         ValidateORD(SHShellFolderView_Message);
  133.         ValidateORD(Shell_GetImageLists);
  134.         ValidateORD(SHGetSpecialFolderPath);
  135.         ValidateORD(StrToOleStrN);
  136.         ValidateORD(ILClone);
  137.         ValidateORD(ILCloneFirst);
  138.         ValidateORD(ILCombine);
  139.         ValidateORD(ILCreateFromPath);
  140.         ValidateORD(ILFindChild);
  141.         ValidateORD(ILFree);
  142.         ValidateORD(ILGetNext);
  143.         ValidateORD(ILGetSize);
  144.         ValidateORD(ILIsEqual);
  145.         ValidateORD(ILRemoveLastID);
  146.         ValidateORD(PathAddBackslash);
  147.         ValidateORD(PathCombine);
  148.         ValidateORD(PathIsExe);
  149.         ValidateORD(PathMatchSpec);
  150.         ValidateORD(SHGetSetSettings);
  151.         ValidateORD(SHILCreateFromPath);
  152.         ValidateORD(SHFree);
  153.         ValidateORD(SHAddFromPropSheetExtArray);
  154.         ValidateORD(SHCreatePropSheetExtArray);
  155.         ValidateORD(SHDestroyPropSheetExtArray);
  156.         ValidateORD(SHReplaceFromPropSheetExtArray);
  157.         ValidateORD(SHCreateDefClassObject);
  158.         ValidateORD(SHGetNetResource);
  159.     }
  160. #endif  // DEBUG
  161. #ifdef DEBUG
  162.     {
  163.         extern LPMALLOC g_pmemTask;
  164.         AssertMsg(g_pmemTask == NULL, TEXT("Somebody called SHAlloc in DllEntry!"));
  165.     }
  166. #endif
  167.     return TRUE;
  168. }
  169. #if defined(WINNT) || defined(DEBUG)
  170. //
  171. //  Table of all window classes we register so we can unregister them
  172. //  at DLL unload.
  173. //
  174. extern const TCHAR c_szDefViewClass[];
  175. extern TCHAR const c_szFakeDesktopClass[];
  176. extern const TCHAR c_szBackgroundPreview2[];
  177. extern const TCHAR c_szComponentPreview[];
  178. extern const TCHAR c_szWindowClassName[];
  179. const LPCTSTR c_rgszClasses[] = {
  180.     c_szDefViewClass,                       // defview.cpp
  181.     TEXT("WOACnslWinPreview"),              // lnkcon.c
  182.     TEXT("WOACnslFontPreview"),             // lnkcon.c
  183.     TEXT("cpColor"),                        // lnkcon.c
  184.     TEXT("cpShowColor"),                    // lnkcon.c
  185.     c_szFakeDesktopClass,                   // restart.c
  186.     c_szStubWindowClass,                    // rundll32.c
  187.     c_szBackgroundPreview2,                 // unicppdbackp.cpp
  188.     c_szComponentPreview,                   // unicppdcompp.cpp
  189.     TEXT(STR_DESKTOPCLASS),                 // unicppdesktop.cpp
  190.     TEXT("MSGlobalFolderOptionsStub"),      // unicppoptions.cpp
  191.     c_szWindowClassName,                    // fsnotify.c
  192.     TEXT("DivWindow"),                      // fsrchdlg.h
  193.     LINKWINDOW_CLASS,                       // linkwnd.cpp
  194.     TEXT("ATL Shell Embedding"),            // unicppdvoc.h
  195.     TEXT("ShellFileSearchControl"),         // fsearch.h
  196.     TEXT("GroupButton"),                    // fsearch
  197.     TEXT("ATL:STATIC"),                     // unicppdeskmovr.cpp
  198.     TEXT("DeskMover"),                      // unicppdeskmovr.cpp
  199. };
  200. #endif
  201. #ifdef WINNT
  202. #define UnregisterWindowClasses() 
  203.     SHUnregisterClasses(HINST_THISDLL, c_rgszClasses, ARRAYSIZE(c_rgszClasses))
  204. #else
  205. // Win95 automatically unregisters classes when a DLL unloads
  206. #define UnregisterWindowClasses()
  207. #endif
  208. void _ProcessDetach(BOOL bProcessShutdown)
  209. {
  210. #ifdef DEBUG
  211.     if (bProcessShutdown)
  212.     {
  213.         // to catch bugs where people use the task allocator at process
  214.         // detatch time (this is a problem becuase OLE32.DLL could be unloaded)
  215.         TaskMem_MakeInvalid(); 
  216.     }
  217. #endif
  218.     FlushRunDlgMRU();
  219.     // Flush the file class before we free any DLLs, to work around a possible
  220.     // Windows 95 loader bug.  The scenario is:
  221.     //
  222.     // MPRSERV.DLL loads SYNCENG to do some user profile file copying.  SYNCENG
  223.     // in turn links to LINKINFO which links to MPR;  it also links to SHELL32,
  224.     // which links to COMCTL32 and delay-links to MPR as well.  When SYNCENG
  225.     // is unloaded, the loader sends process detach notifications to the entire
  226.     // DLL tree.  When we unload our reference to MPR here, that sometimes
  227.     // seems to cause the loader to continue with its process detach messages
  228.     // to more DLLs in the tree, including COMCTL32.  COMCTL32 responds to this
  229.     // by destroying the shared heap.  Unfortunately we then return back to
  230.     // this chunk of code (we're in SHELL32, remember), and call FlushFileClass.
  231.     // That tries to access COMCTL32's shared heap and faults.
  232.     //
  233.     // Since this is really a bug in the Windows 95 loader, we work around it
  234.     // here, by calling FlushFileClass (and anything else that references the
  235.     // shared heap) before any FreeLibrary calls.
  236.     //
  237.     // Do not reference the shared heap after the block of Xxxx_Term() calls
  238.     // below.
  239.     // -- gregj, 03/26/97
  240.     // Flush the file class cache, some app may have changed associations
  241.     // BUGBUG is this too often?
  242.     FlushFileClass();
  243.     //
  244.     // All the per-instance terminate code should be done here.
  245.     // WARNING: Do not touch the shared heap below this point!
  246.     //
  247.     if (!bProcessShutdown)
  248.     {
  249.         // some of these may use the task allocator. we can only do
  250.         // this when we our DLL is being unloaded in a process, not
  251.         // at process term since OLE32 might not be around to be called
  252.         // at process shutdown time this memory will be freed as a result
  253.         // of the process address space going away.
  254.         SpecialFolderIDTerminate();
  255.         BitBucket_Terminate();
  256.         UltRoot_Term();
  257.         RLTerminate();          // close our use of the Registry list...
  258.         DAD_ProcessDetach();
  259.         CDrives_Terminate();
  260.         NetRoot_Terminate();
  261.         CopyHooksTerminate();
  262.         IconOverlayManagerTerminate();
  263.         // being unloaded via FreeLibrary, then do some more stuff.
  264.         // Don't need to do this on process terminate.
  265.         UnregisterWindowClasses();
  266.         FreeExtractIconInfo(-1);
  267.     }
  268.     if (InterlockedDecrement(&g_cProcesses) == 0)
  269.     {
  270.         // On Win95 where we have global global data only do 
  271.         // this on the very last proces detatch. g_cProcesses
  272.         // is a global global variable that tells how many process are
  273.         // using shell32.dll
  274.         
  275.         // on NT this is value is always not global so we always execute this code
  276.         DestroyHashItemTable(NULL);
  277.         FileIconTerm();
  278.         SHChangeNotifyTerminate(TRUE);
  279. #ifndef WINNT
  280.         CMtPt_FakeVolatileKeys();
  281. #endif
  282.     }
  283.     else
  284.         SHChangeNotifyTerminate(FALSE);  // still some clients out there
  285.     // global resources that we need to free in all cases
  286.     CMtPt_FinalCleanUp();
  287.     if (g_hkcrCLSID)
  288.         RegCloseKey(g_hkcrCLSID);
  289.     if (g_hklmExplorer)
  290.         RegCloseKey(g_hklmExplorer);
  291.     SHDestroyCachedGlobalCounter(&g_hCounter);
  292.     SHDestroyCachedGlobalCounter(&g_hRestrictions);
  293.     SHDestroyCachedGlobalCounter(&g_hSettings);
  294. #ifdef WINNT
  295.     if (g_hklmApprovedExt && g_hklmApprovedExt != INVALID_HANDLE_VALUE)
  296.         RegCloseKey(g_hklmApprovedExt);
  297.     DeleteCriticalSection(&g_csDll);
  298.     DeleteCriticalSection(&g_csPrinters);
  299. #endif
  300. }
  301. BOOL _ThreadDetach()
  302. {
  303.     ASSERTNONCRITICAL           // Thread shouldn't term while holding CS
  304.     DAD_ThreadDetach();
  305.     return TRUE;
  306. }
  307. #ifndef WINNT
  308. // created by the thunk scripts
  309. BOOL WINAPI Shl3216_ThunkConnect32(LPCTSTR pszDll16, LPCTSTR pszDll32, HANDLE hIinst, DWORD dwReason);
  310. BOOL WINAPI Shl1632_ThunkConnect32(LPCTSTR pszDll16, LPCTSTR pszDll32, HANDLE hIinst, DWORD dwReason);
  311. #endif
  312. // ccover uses c run time, so we need to have entry point called DllMain
  313. #if defined(CCOVER) || defined(_WIN64)
  314. #define DllEntry DllMain
  315. #endif
  316. STDAPI_(BOOL) DllEntry(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
  317. {
  318. #ifndef WINNT
  319.     if (!Shl3216_ThunkConnect32(c_szShell16Dll, c_szShell32Dll, hDll, dwReason))
  320.         return FALSE;
  321.     if (!Shl1632_ThunkConnect32(c_szShell16Dll, c_szShell32Dll, hDll, dwReason))
  322.         return FALSE;
  323. #endif
  324. #ifdef DEBUG
  325.     g_bInDllEntry = TRUE;
  326. #endif
  327.     switch(dwReason) {
  328.     case DLL_PROCESS_ATTACH:
  329.         CcshellGetDebugFlags();     // Don't put this line under #ifdef
  330.         _ProcessAttach(hDll);
  331.         break;
  332.     case DLL_PROCESS_DETACH:
  333.         _ProcessDetach(lpReserved != NULL);
  334.         break;
  335.     case DLL_THREAD_DETACH:
  336.         _ThreadDetach();
  337.         break;
  338.     default:
  339.         break;
  340.     }
  341.     ATL_DllMain(hDll, dwReason, lpReserved);
  342. #ifdef DEBUG
  343.     g_bInDllEntry = FALSE;
  344. #endif
  345.     return TRUE;
  346. }
  347. #ifdef DEBUG
  348. LRESULT WINAPI SendMessageD( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
  349. {
  350.     ASSERTNONCRITICAL;
  351. #ifdef UNICODE
  352.     return SendMessageW(hWnd, Msg, wParam, lParam);
  353. #else
  354.     return SendMessageA(hWnd, Msg, wParam, lParam);
  355. #endif
  356. }
  357. //
  358. //  In DEBUG, make sure every class we register lives in the c_rgszClasses
  359. //  table so we can clean up properly at DLL unload.  NT does not automatically
  360. //  unregister classes when a DLL unloads, so we have to do it manually.
  361. //
  362. ATOM WINAPI RegisterClassD(CONST WNDCLASS *pwc)
  363. {
  364.     int i;
  365.     for (i = 0; i < ARRAYSIZE(c_rgszClasses); i++) {
  366.         if (lstrcmpi(c_rgszClasses[i], pwc->lpszClassName) == 0) {
  367.             return RealRegisterClass(pwc);
  368.         }
  369.     }
  370.     AssertMsg(0, TEXT("Class %s needs to be added to the c_rgszClasses list"), pwc->lpszClassName);
  371.     return 0;
  372. }
  373. ATOM WINAPI RegisterClassExD(CONST WNDCLASSEX *pwc)
  374. {
  375.     int i;
  376.     for (i = 0; i < ARRAYSIZE(c_rgszClasses); i++) {
  377.         if (lstrcmpi(c_rgszClasses[i], pwc->lpszClassName) == 0) {
  378.             return RealRegisterClassEx(pwc);
  379.         }
  380.     }
  381.     AssertMsg(0, TEXT("Class %s needs to be added to the c_rgszClasses list"), pwc->lpszClassName);
  382.     return 0;
  383. }
  384. //
  385. //  In DEBUG, send FindWindow through a wrapper that ensures that the
  386. //  critical section is not taken.  FindWindow'ing for a window title
  387. //  sends inter-thread WM_GETTEXT messages, which is not obvious.
  388. //
  389. STDAPI_(HWND) FindWindowD(LPCTSTR lpClassName, LPCTSTR lpWindowName)
  390. {
  391.     return FindWindowExD(NULL, NULL, lpClassName, lpWindowName);
  392. }
  393. STDAPI_(HWND) FindWindowExD(HWND hwndParent, HWND hwndChildAfter, LPCTSTR lpClassName, LPCTSTR lpWindowName)
  394. {
  395.     if (lpWindowName) {
  396.         ASSERTNONCRITICAL;
  397.     }
  398.     return RealFindWindowEx(hwndParent, hwndChildAfter, lpClassName, lpWindowName);
  399. }
  400. #endif // DEBUG
  401. STDAPI DllCanUnloadNow()
  402. {
  403.     // shell32 won't be able to be unloaded since there are lots of APIs and
  404.     // other non COM things that will need to keep it loaded
  405.     return S_FALSE;
  406. }