/*++

Microsoft Windows
Copyright (C) Microsoft Corporation, 1981 - 1998

Module Name:

    irftp.cpp

Abstract:



Author:

    Rahul Thombre (RahulTh) 4/30/1998

Revision History:

    4/30/1998   RahulTh

    Created this module.

--*/

// irftp.cpp : Defines the class behaviors for the application.
//

#include "precomp.hxx"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

BOOL LoadGlobalStrings();

/////////////////////////////////////////////////////////////////////////////
// CIrftpApp

BEGIN_MESSAGE_MAP(CIrftpApp, CWinApp)
    //{{AFX_MSG_MAP(CIrftpApp)
        // NOTE - the ClassWizard will add and remove mapping macros here.
        //    DO NOT EDIT what you see in these blocks of generated code!
    //}}AFX_MSG
    ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CIrftpApp construction

CIrftpApp::CIrftpApp()
{

// TODO: add construction code here,
    // Place all significant initialization in InitInstance
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CIrftpApp object

CIrftpApp theApp;

////////////////////////////////////////////////////////////////////////////
// The instance handle for this app.
HINSTANCE g_hInstance;

////////////////////////////////////////////////////////////////////////////
//RPC handle
RPC_BINDING_HANDLE g_hIrRpcHandle = NULL;

///////////////////////////////////////////////////////////////////////////
//the main application UI. this is now global because it might be
//invoked from multiple file, especially the RPC server functions
CIrftpDlg AppUI;

///////////////////////////////////////////////////////////////////////////
//the controller window for the application. This is necessary to
//create the illusion of parentless send progress dialog boxes.
//actually it is not possible to have parentless and modeless dialog
//boxes. Thus, these dialog boxes actually have the controller window
//as their parent
//This is necessary because the AppUI may come and go and in fact
//never come up at all.
CController* appController = NULL;

////////////////////////////////////////////////////////////////////////////
//global variable that keeps track of the number of UI components displayed
//by irftp at the moment. Note: we start with -1 because we don't want to
//count the first CController window which is the main app. window.
//
LONG g_lUIComponentCount = -1;

////////////////////////////////////////////////////////////////////////////
//global variable that keeps track of the handle to the help window (if any)
//The HtmlHelp window is the only one that cannot be tracked using the
//g_lUIComponentCount. So we need this var. to figure out if the help window
//is still up.
HWND g_hwndHelp = NULL;

////////////////////////////////////////////////////////////////////////////
//global variable that keeps track of whether there is a shortcut to
//the app on the desktop or not
//0 implies that there is a link on the desktop and -1 implies that there
//is no link on the desktop.
//this value is basically an indicator of not only the presence of
//the shortcut on the desktop, but also of the link in the send to
//folder
LONG g_lLinkOnDesktop = -1;
//the path of the desktop folder.
TCHAR g_lpszDesktopFolder[MAX_PATH];
//the path to the send to folder;
TCHAR g_lpszSendToFolder[MAX_PATH];

////////////////////////////////////////////////////////////////////////////
//the list of devices in range
CDeviceList g_deviceList;

/////////////////////////////////////////////////////////////////////////////
// CIrftpApp initialization

BOOL CIrftpApp::InitInstance()
{
    DWORD Status;
    error_status_t err;
    CError      error;
    BOOL        bSetForeground = FALSE;
    int         i = 0;
    HWND        hwndApp = NULL;
    HANDLE      hMutex = NULL;
    BOOL        fFirstInstance = FALSE;

    AfxEnableControlContainer();

    //set the global instance handle
    g_hInstance = AfxGetInstanceHandle();

    CCommandLine cLine;
    ParseCommandLine (cLine);

    if(cLine.m_fInvalidParams)  //if invalid command line parameters, terminate.
    {
        error.ShowMessage (IDS_INVALID_PARAMETERS);
        return FALSE;   //exit the app., first instance or not.
    }

    //check if another instance is already running and act accordingly.
    hMutex = CreateMutex (NULL, FALSE, SINGLE_INST_MUTEX);
    Status = GetLastError();
    if (hMutex)
    {
        fFirstInstance = (ERROR_ALREADY_EXISTS != Status);
    }
    else
    {
        //we could not create the mutex, so must fail.
        return FALSE;
    }

    g_hIrRpcHandle = GetRpcHandle();

    //
    // Load strings.
    //
    if (FALSE == LoadGlobalStrings())
        {
        return FALSE;
        }

    if (!fFirstInstance)
    {
        hwndApp = GetPrimaryAppWindow();
        //note: it is important to successfully set the the first instance of the app. as the foreground window.
        //since the first instance has already started, it is very unlikely that it will be the foreground process
        //therefore it will be unable to set itself as the foreground process and therefore any calls to SetActiveWindow
        //etc. in that instance will not cause any changes in the Z-order or input focus. Therefore, this instance needs
        //to make the first instance the foreground process so that any dialogs etc. put up by the windows do not show
        //up obscured by other apps. or without focus. The current instance is able to set the first instance as the
        //foreground process because this instance is either itself the foreground process or is started by the current
        //foreground process.
        if (hwndApp && (!cLine.m_fHideApp))
        {
            bSetForeground = ::SetForegroundWindow (hwndApp);
        }
        if (cLine.m_fFilesProvided)
                InitiateFileTransfer (g_hIrRpcHandle, cLine.m_iListLen, cLine.m_lpszFilesList);
        else if (cLine.m_fShowSettings)
                DisplaySettings(g_hIrRpcHandle);
        else if (!cLine.m_fHideApp)
                PopupUI (g_hIrRpcHandle);
        //do nothing otherwise.

        //for some reason, SetForegroundWindow does not succeed if the window which we are trying to put in the
        //foreground does not have any visible windows. So if a user transfers some files and then dismisses the
        //wireless link dialog, then at this point, the hidden parent window is not the foreground window. So, we
        //try for 10 seconds to get the window in the foreground. It is okay to spin here because other than getting
        //the window to the top of the Z-order everything else has already been done. Here, we just want to give the
        //shell enough time to put up the common file open dialog. Note that we stop spinning the moment we succeed
        //in setting the first instance as the foreground window.
        if (!bSetForeground && hwndApp && (!cLine.m_fHideApp))
        {
            i = 0;
            do
            {
                if (::SetForegroundWindow (hwndApp))
                    break;
                else
                    Sleep (100);
            } while ( i++ < 100 );
        }

        CloseHandle (hMutex);
        return FALSE;   //exit the app. rather than starting the message pump
    }

    // Standard initialization
    // If you are not using these features and wish to reduce the size
    //  of your final executable, you should remove from the following
    //  the specific initialization routines you do not need.

#ifdef _AFXDLL
    Enable3dControls();         // Call this when using MFC in a shared DLL
#else
    Enable3dControlsStatic();   // Call this when linking to MFC statically
#endif

     //if we reach here, it means that this is the first instance of the app.
    m_pMainWnd = appController = new CController (cLine.m_fHideApp);
    if (!appController)
        {
        return FALSE;
        }
    appController->ShowWindow(SW_HIDE);
    appController->SetWindowText (MAIN_WINDOW_TITLE);
    g_lpszDesktopFolder[0] = '\0';  //precautionary measures
    g_lpszSendToFolder [0] = '\0';

    if(!InitRPCServer())
        {
        return FALSE;   //exit the app. if the RPC server cannot be started
        }

    if (cLine.m_fFilesProvided)
        _InitiateFileTransfer(NULL, cLine.m_iListLen, cLine.m_lpszFilesList);
    else if (cLine.m_fShowSettings)
        _DisplaySettings(NULL);
    else if (!cLine.m_fHideApp)
        _PopupUI(NULL);
    //else do nothing, since the app is supposed to be hidden

    return TRUE;        //start the message pump. RPC server is already running
}

GLOBAL_STRINGS g_Strings;

BOOL
LoadGlobalStrings()
{
#define LOAD_STRING(id, str)                                                     \
    if (0 == LoadString( g_hInstance, id, g_Strings.str, sizeof(g_Strings.str)/sizeof(wchar_t))) \
        {                                                                        \
        return FALSE;                                                            \
        }

    LOAD_STRING( IDS_CLOSE, Close )
    LOAD_STRING( IDS_NODESC_ERROR, ErrorNoDescription )
    LOAD_STRING( IDS_COMPLETED, CompletedSuccess )
    LOAD_STRING( IDS_RECV_ERROR, ReceiveError )
    LOAD_STRING( IDS_CONNECTING, Connecting )
    LOAD_STRING( IDS_RECV_CANCELLED, RecvCancelled )

    return TRUE;
}