/*++

Copyright (c) 1990-1998,  Microsoft Corporation  All rights reserved.

Module Name:

    init.c

Abstract:

    This module contains the init routines for the Win32 common dialogs.

Revision History:

--*/

// precompiled headers
#include "precomp.h"
#pragma hdrstop

//
//  External Declarations.
//

extern HDC hdcMemory;
extern HBITMAP hbmpOrigMemBmp;

extern CRITICAL_SECTION g_csLocal;
extern CRITICAL_SECTION g_csNetThread;

// TLS index to get current dlg info for the current thread
extern DWORD g_tlsiCurDlg;   

// TLS index to get most recent ExtError for the current thread
extern DWORD g_tlsiExtError; 

// TLS index to get LangID used for the current thread
extern DWORD g_tlsLangID;

extern HANDLE hMPR;
extern HANDLE hMPRUI;
extern HANDLE hLNDEvent;

extern DWORD dwNumDisks;
extern OFN_DISKINFO gaDiskInfo[MAX_DISKS];

extern DWORD cbNetEnumBuf;
extern LPTSTR gpcNetEnumBuf;

extern RECT g_rcDlg;

extern TCHAR g_szInitialCurDir[MAX_PATH];

//
//  Global Variables.
//

WCHAR szmsgLBCHANGEW[]          = LBSELCHSTRINGW;
WCHAR szmsgSHAREVIOLATIONW[]    = SHAREVISTRINGW;
WCHAR szmsgFILEOKW[]            = FILEOKSTRINGW;
WCHAR szmsgCOLOROKW[]           = COLOROKSTRINGW;
WCHAR szmsgSETRGBW[]            = SETRGBSTRINGW;
WCHAR szCommdlgHelpW[]          = HELPMSGSTRINGW;

TCHAR szShellIDList[]           = CFSTR_SHELLIDLIST;

BOOL g_bMirroredOS              = FALSE;
//
//  Private message for WOW to indicate 32-bit logfont
//  needs to be thunked back to 16-bit log font.
//
CHAR szmsgWOWLFCHANGE[]         = "WOWLFChange";

//
//  Private message for WOW to indicate 32-bit directory needs to be
//  thunked back to 16-bit task directory.
//
CHAR szmsgWOWDIRCHANGE[]        = "WOWDirChange";
CHAR szmsgWOWCHOOSEFONT_GETLOGFONT[]  = "WOWCHOOSEFONT_GETLOGFONT";

CHAR szmsgLBCHANGEA[]           = LBSELCHSTRINGA;
CHAR szmsgSHAREVIOLATIONA[]     = SHAREVISTRINGA;
CHAR szmsgFILEOKA[]             = FILEOKSTRINGA;
CHAR szmsgCOLOROKA[]            = COLOROKSTRINGA;
CHAR szmsgSETRGBA[]             = SETRGBSTRINGA;
CHAR szCommdlgHelpA[]           = HELPMSGSTRINGA;

UINT g_cfCIDA;





////////////////////////////////////////////////////////////////////////////
//
//  FInitColor
//
////////////////////////////////////////////////////////////////////////////

extern DWORD rgbClient;
extern HBITMAP hRainbowBitmap;

int FInitColor(
    HANDLE hInst)
{
    cyCaption = (short)GetSystemMetrics(SM_CYCAPTION);
    cyBorder = (short)GetSystemMetrics(SM_CYBORDER);
    cxBorder = (short)GetSystemMetrics(SM_CXBORDER);
    cyVScroll = (short)GetSystemMetrics(SM_CYVSCROLL);
    cxVScroll = (short)GetSystemMetrics(SM_CXVSCROLL);
    cxSize = (short)GetSystemMetrics(SM_CXSIZE);

    rgbClient = GetSysColor(COLOR_3DFACE);

    hRainbowBitmap = 0;

    return (TRUE);
    hInst;
}


////////////////////////////////////////////////////////////////////////////
//
//  FInitFile
//
////////////////////////////////////////////////////////////////////////////

BOOL FInitFile(
    HANDLE hins)
{
    bMouse = GetSystemMetrics(SM_MOUSEPRESENT);

    wWinVer = 0x0A0A;

    //
    //  Initialize these to reality.
    //
#if DPMICDROMCHECK
    wCDROMIndex = InitCDROMIndex((LPWORD)&wNumCDROMDrives);
#endif

    //
    // special WOW messages
    //
    msgWOWLFCHANGE       = RegisterWindowMessageA((LPSTR)szmsgWOWLFCHANGE);
    msgWOWDIRCHANGE      = RegisterWindowMessageA((LPSTR)szmsgWOWDIRCHANGE);
    msgWOWCHOOSEFONT_GETLOGFONT = RegisterWindowMessageA((LPSTR)szmsgWOWCHOOSEFONT_GETLOGFONT);

    msgLBCHANGEA         = RegisterWindowMessageA((LPSTR)szmsgLBCHANGEA);
    msgSHAREVIOLATIONA   = RegisterWindowMessageA((LPSTR)szmsgSHAREVIOLATIONA);
    msgFILEOKA           = RegisterWindowMessageA((LPSTR)szmsgFILEOKA);
    msgCOLOROKA          = RegisterWindowMessageA((LPSTR)szmsgCOLOROKA);
    msgSETRGBA           = RegisterWindowMessageA((LPSTR)szmsgSETRGBA);

#ifdef UNICODE
    msgLBCHANGEW         = RegisterWindowMessageW((LPWSTR)szmsgLBCHANGEW);
    msgSHAREVIOLATIONW   = RegisterWindowMessageW((LPWSTR)szmsgSHAREVIOLATIONW);
    msgFILEOKW           = RegisterWindowMessageW((LPWSTR)szmsgFILEOKW);
    msgCOLOROKW          = RegisterWindowMessageW((LPWSTR)szmsgCOLOROKW);
    msgSETRGBW           = RegisterWindowMessageW((LPWSTR)szmsgSETRGBW);
#else
    msgLBCHANGEW         = msgLBCHANGEA;
    msgSHAREVIOLATIONW   = msgSHAREVIOLATIONA;
    msgFILEOKW           = msgFILEOKA;
    msgCOLOROKW          = msgCOLOROKA;
    msgSETRGBW           = msgSETRGBA;
#endif

    g_cfCIDA             = RegisterClipboardFormat(szShellIDList);

    return (TRUE);
}


////////////////////////////////////////////////////////////////////////////
//
//  LibMain
//
//  Initializes any instance specific data needed by functions in the
//  common dialogs.
//
//  Returns:   TRUE    - success
//             FALSE   - failure
//
////////////////////////////////////////////////////////////////////////////

// ccover needs to link to C-runtime, so we rename LibMain to DllMain
#ifdef CCOVER 
#define LibMain DllMain
#endif

BOOL LibMain(
    HANDLE hModule,
    DWORD dwReason,
    LPVOID lpRes)
{
    switch (dwReason)
    {
        case ( DLL_THREAD_ATTACH ) :
        case ( DLL_THREAD_DETACH ) :
        {
            //
            //  Threads can only enter and leave the comdlg32 dll from the
            //  Get{Open,Save}FileName apis, so the TLS lpCurDlg alloc is
            //  done inside the InitFileDlg routine in fileopen.c
            //
            return (TRUE);
            break;
        }
        case ( DLL_PROCESS_ATTACH ) :
        {
            g_hinst = (HANDLE)hModule;

            if (!FInitColor(g_hinst) || !FInitFile(g_hinst))
            {
                goto CantInit;
            }

            DisableThreadLibraryCalls(hModule);

            //
            //  msgHELP is sent whenever a help button is pressed in one of
            //  the common dialogs (provided an owner was declared and the
            //  call to RegisterWindowMessage doesn't fail).
            //
            msgHELPA = RegisterWindowMessageA((LPSTR)szCommdlgHelpA);
#ifdef UNICODE
            msgHELPW = RegisterWindowMessageW((LPWSTR)szCommdlgHelpW);
#else
            msgHELPW = msgHELPA;
#endif

            //
            //  Need a semaphore locally for managing array of disk info.
            //
            InitializeCriticalSection(&g_csLocal);

            //
            //  Need a semaphore for control access to CreateThread.
            //
            InitializeCriticalSection(&g_csNetThread);

            //
            //  Allocate a tls index for curdlg so we can make it per-thread.
            //
            if ((g_tlsiCurDlg = TlsAlloc()) != 0xFFFFFFFF)
            {
                // mark the list as empty
                TlsSetValue(g_tlsiCurDlg, (LPVOID) 0);
            }
            else
            {
                StoreExtendedError(CDERR_INITIALIZATION);
                goto CantInit;
            }

            //
            //  Store the current directory on process attach.
            //
            GetCurrentDirectory(ARRAYSIZE(g_szInitialCurDir), g_szInitialCurDir);

            //
            //  Allocate a tls index for extended error.
            //
            if ((g_tlsiExtError = TlsAlloc()) == 0xFFFFFFFF)
            {
                StoreExtendedError(CDERR_INITIALIZATION);
                goto CantInit;
            }

            //
            //  Allocate a tls index for LangID so we can make it per-thread.
            //  it heavily used by CDLoadString.
            //
            if ((g_tlsLangID = TlsAlloc()) != 0xFFFFFFFF)
            {
                // mark the list as Neutral
                TlsSetValue(g_tlsLangID, (LPVOID) MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
            }
            else
            {
                StoreExtendedError(CDERR_INITIALIZATION);
                goto CantInit;
            }



            dwNumDisks = 0;
            gpcNetEnumBuf = NULL;

            //
            //  NetEnumBuf allocated in ListNetDrivesHandler.
            //
            cbNetEnumBuf = WNETENUM_BUFFSIZE;

            hMPR = NULL;
            hMPRUI = NULL;

            hLNDEvent = NULL;

            //
            //  For file open dialog.
            //
            g_rcDlg.left = g_rcDlg.right = g_rcDlg.top = g_rcDlg.bottom = 0;

            g_bMirroredOS = IS_MIRRORING_ENABLED();
            return (TRUE);
            break;
        }
        case ( DLL_PROCESS_DETACH ) :
        {
            //
            //  We only want to do our clean up work if we are being called
            //  with freelibrary, not if the process is ending.
            //
            if (lpRes == NULL)
            {
                TermFile();
                TermPrint();
                TermColor();
                TermFont();

                TlsFree(g_tlsiCurDlg);
                TlsFree(g_tlsiExtError);
                TlsFree(g_tlsLangID);

                DeleteCriticalSection(&g_csLocal);
                DeleteCriticalSection(&g_csNetThread);
            }

            return (TRUE);
            break;
        }
    }

CantInit:
    return (FALSE);
    lpRes;
}
