/*
 * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include "awt.h"
#include <windowsx.h>
#include <shellapi.h>
#include <shlwapi.h>

#include "awt_Toolkit.h"
#include "awt_TrayIcon.h"
#include "awt_AWTEvent.h"

#include <java_awt_event_InputEvent.h>

/***********************************************************************/
// Struct for _SetToolTip() method
struct SetToolTipStruct {
    jobject trayIcon;
    jstring tooltip;
};
// Struct for _SetIcon() method
struct SetIconStruct {
    jobject trayIcon;
    HICON hIcon;
};
// Struct for _UpdateIcon() method
struct UpdateIconStruct {
    jobject trayIcon;
    jboolean update;
};
// Struct for _DisplayMessage() method
struct DisplayMessageStruct {
    jobject trayIcon;
    jstring caption;
    jstring text;
    jstring msgType;
};

typedef struct tagBitmapheader  {
    BITMAPV5HEADER bmiHeader;
    DWORD            dwMasks[256];
} Bitmapheader, *LPBITMAPHEADER;


/************************************************************************
 * AwtTrayIcon fields
 */

jfieldID AwtTrayIcon::idID;
jfieldID AwtTrayIcon::actionCommandID;

HWND AwtTrayIcon::sm_msgWindow = NULL;
AwtTrayIcon::TrayIconListItem* AwtTrayIcon::sm_trayIconList = NULL;
int AwtTrayIcon::sm_instCount = 0;

/************************************************************************
 * AwtTrayIcon methods
 */

AwtTrayIcon::AwtTrayIcon() {
    ::ZeroMemory(&m_nid, sizeof(m_nid));

    if (sm_instCount++ == 0 && AwtTrayIcon::sm_msgWindow == NULL) {
        sm_msgWindow = AwtTrayIcon::CreateMessageWindow();
    }
    m_mouseButtonClickAllowed = 0;
}

AwtTrayIcon::~AwtTrayIcon() {
}

void AwtTrayIcon::Dispose() {
    SendTrayMessage(NIM_DELETE);
    UnlinkObjects();

    if (--sm_instCount == 0) {
        AwtTrayIcon::DestroyMessageWindow();
    }

    AwtObject::Dispose();
}

LPCTSTR AwtTrayIcon::GetClassName() {
    return TEXT("SunAwtTrayIcon");
}

void AwtTrayIcon::FillClassInfo(WNDCLASS *lpwc)
{
    lpwc->style         = 0L;
    lpwc->lpfnWndProc   = (WNDPROC)TrayWindowProc;
    lpwc->cbClsExtra    = 0;
    lpwc->cbWndExtra    = 0;
    lpwc->hInstance     = AwtToolkit::GetInstance().GetModuleHandle(),
    lpwc->hIcon         = AwtToolkit::GetInstance().GetAwtIcon();
    lpwc->hCursor       = NULL;
    lpwc->hbrBackground = NULL;
    lpwc->lpszMenuName  = NULL;
    lpwc->lpszClassName = AwtTrayIcon::GetClassName();
}

void AwtTrayIcon::RegisterClass()
{
    WNDCLASS  wc;

    ::ZeroMemory(&wc, sizeof(wc));

    if (!::GetClassInfo(AwtToolkit::GetInstance().GetModuleHandle(),
                        AwtTrayIcon::GetClassName(), &wc))
    {
        AwtTrayIcon::FillClassInfo(&wc);
        ATOM atom = ::RegisterClass(&wc);
        DASSERT(atom != 0);
    }
}

void AwtTrayIcon::UnregisterClass()
{
    ::UnregisterClass(AwtTrayIcon::GetClassName(), AwtToolkit::GetInstance().GetModuleHandle());
}

HWND AwtTrayIcon::CreateMessageWindow()
{
    AwtTrayIcon::RegisterClass();

    HWND hWnd = ::CreateWindow(AwtTrayIcon::GetClassName(), TEXT("TrayMessageWindow"),
                               0, 0, 0, 0, 0, NULL, NULL,
                               AwtToolkit::GetInstance().GetModuleHandle(), NULL);
    return hWnd;
}

void AwtTrayIcon::DestroyMessageWindow()
{
    ::DestroyWindow(AwtTrayIcon::sm_msgWindow);
    AwtTrayIcon::sm_msgWindow = NULL;
    AwtTrayIcon::UnregisterClass();
}

AwtTrayIcon* AwtTrayIcon::Create(jobject self, jobject parent)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    jobject target = NULL;
    AwtTrayIcon* awtTrayIcon = NULL;

    target  = env->GetObjectField(self, AwtObject::targetID);
    DASSERT(target);

    awtTrayIcon = new AwtTrayIcon();
    awtTrayIcon->LinkObjects(env, self);
    awtTrayIcon->InitNID(env->GetIntField(target, AwtTrayIcon::idID));
    awtTrayIcon->AddTrayIconItem(awtTrayIcon->GetID());

    env->DeleteLocalRef(target);
    return awtTrayIcon;
}

void AwtTrayIcon::InitNID(UINT uID)
{
    // fix for 6271589: we MUST set the size of the structure to match
    // the shell version, otherwise some errors may occur (like missing
    // balloon messages on win2k)
    DLLVERSIONINFO dllVersionInfo;
    dllVersionInfo.cbSize = sizeof(DLLVERSIONINFO);
    int shellVersion = 5; // WIN_2000
    // MSDN: DllGetVersion should not be implicitly called, but rather
    // loaded using GetProcAddress
    HMODULE hShell = JDK_LoadSystemLibrary("Shell32.dll");
    if (hShell != NULL) {
        DLLGETVERSIONPROC proc = (DLLGETVERSIONPROC)GetProcAddress(hShell, "DllGetVersion");
        if (proc != NULL) {
            if (proc(&dllVersionInfo) == NOERROR) {
                shellVersion = dllVersionInfo.dwMajorVersion;
            }
        }
    }
    FreeLibrary(hShell);
    switch (shellVersion) {
        case 5: // WIN_2000
            m_nid.cbSize = (BYTE *)(&m_nid.guidItem) - (BYTE *)(&m_nid.cbSize);
            break;
        case 6: // WIN_XP
            m_nid.cbSize = (BYTE *)(&m_nid.hBalloonIcon) - (BYTE *)(&m_nid.cbSize);
            break;
        default: // WIN_VISTA
            m_nid.cbSize = sizeof(m_nid);
            break;
    }
    m_nid.hWnd = AwtTrayIcon::sm_msgWindow;
    m_nid.uID = uID;
    m_nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
    m_nid.uCallbackMessage = WM_AWT_TRAY_NOTIFY;
    m_nid.hIcon = AwtToolkit::GetInstance().GetAwtIcon();
    m_nid.szTip[0] = '\0';
    m_nid.uVersion = NOTIFYICON_VERSION;
}

BOOL AwtTrayIcon::SendTrayMessage(DWORD dwMessage)
{
    return Shell_NotifyIcon(dwMessage, (PNOTIFYICONDATA)&m_nid);
}

static UINT lastMessage = WM_NULL;

LRESULT CALLBACK AwtTrayIcon::TrayWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    LRESULT retValue = 0;
    MsgRouting mr = mrDoDefault;
    static UINT s_msgTaskbarCreated;

    switch(uMsg)
    {
        case WM_CREATE:
            // Fix for CR#6369062
            s_msgTaskbarCreated = ::RegisterWindowMessage(TEXT("TaskbarCreated"));
            break;
        case WM_AWT_TRAY_NOTIFY:
            if (hwnd == AwtTrayIcon::sm_msgWindow) {
                AwtTrayIcon* trayIcon = AwtTrayIcon::SearchTrayIconItem((UINT)wParam);
                if (trayIcon != NULL) {
                    mr = trayIcon->WmAwtTrayNotify(wParam, lParam);
                }
            }
            break;
        default:
            if(uMsg == s_msgTaskbarCreated) {
                if (hwnd == AwtTrayIcon::sm_msgWindow) {
                    mr = WmTaskbarCreated();
                }
            }
            break;
    }

    if (mr != mrConsume) {
        retValue = ::DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return retValue;
}

/*
 * This function processes callback messages for taskbar icons.
 */
MsgRouting AwtTrayIcon::WmAwtTrayNotify(WPARAM wParam, LPARAM lParam)
{
    MsgRouting mr = mrDoDefault;

    POINT pos = {0, 0};
    ::GetCursorPos(&pos);

    lastMessage = (UINT)lParam;
    UINT flags = AwtToolkit::GetInstance().GetMouseKeyState();

    switch((UINT)lParam)
    {
        case WM_MOUSEMOVE:
            mr = WmMouseMove(flags, pos.x, pos.y);
            break;
        case WM_LBUTTONDBLCLK:
        case WM_LBUTTONDOWN:
            mr = WmMouseDown(flags, pos.x, pos.y, LEFT_BUTTON);
            break;
        case WM_LBUTTONUP:
            mr = WmMouseUp(flags, pos.x, pos.y, LEFT_BUTTON);
            break;
        case WM_RBUTTONDBLCLK:
        case WM_RBUTTONDOWN:
            mr = WmMouseDown(flags, pos.x, pos.y, RIGHT_BUTTON);
            break;
        case WM_RBUTTONUP:
            mr = WmMouseUp(flags, pos.x, pos.y, RIGHT_BUTTON);
            break;
        case WM_MBUTTONDBLCLK:
        case WM_MBUTTONDOWN:
            mr = WmMouseDown(flags, pos.x, pos.y, MIDDLE_BUTTON);
            break;
        case WM_MBUTTONUP:
            mr = WmMouseUp(flags, pos.x, pos.y, MIDDLE_BUTTON);
            break;
        case WM_CONTEXTMENU:
            mr = WmContextMenu(0, pos.x, pos.y);
            break;
        case NIN_KEYSELECT:
            mr = WmKeySelect(0, pos.x, pos.y);
            break;
        case NIN_SELECT:
            mr = WmSelect(0, pos.x, pos.y);
            break;
        case NIN_BALLOONUSERCLICK:
            mr = WmBalloonUserClick(0, pos.x, pos.y);
            break;
    }
    return mr;
}

/* Double-click variables. */
static jlong multiClickTime = ::GetDoubleClickTime();
static int multiClickMaxX = ::GetSystemMetrics(SM_CXDOUBLECLK);
static int multiClickMaxY = ::GetSystemMetrics(SM_CYDOUBLECLK);
static AwtTrayIcon* lastClickTrIc = NULL;
static jlong lastTime = 0;
static int lastClickX = 0;
static int lastClickY = 0;
static int lastButton = 0;
static int clickCount = 0;

MsgRouting AwtTrayIcon::WmMouseDown(UINT flags, int x, int y, int button)
{
    jlong now = TimeHelper::getMessageTimeUTC();
    jint javaModif = AwtComponent::GetJavaModifiers();

    if (lastClickTrIc == this &&
        lastButton == button &&
        (now - lastTime) <= multiClickTime &&
        abs(x - lastClickX) <= multiClickMaxX &&
        abs(y - lastClickY) <= multiClickMaxY)
    {
        clickCount++;
    } else {
        clickCount = 1;
        lastClickTrIc = this;
        lastButton = button;
        lastClickX = x;
        lastClickY = y;
    }
    lastTime = now;
    // it's needed only if WM_LBUTTONUP doesn't come for some reason
    m_mouseButtonClickAllowed |= AwtComponent::GetButtonMK(button);

    MSG msg;
    AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);

    SendMouseEvent(java_awt_event_MouseEvent_MOUSE_PRESSED, now, x, y,
                   javaModif, clickCount, JNI_FALSE,
                   AwtComponent::GetButton(button), &msg);

    return mrConsume;
}

MsgRouting AwtTrayIcon::WmMouseUp(UINT flags, int x, int y, int button)
{
    MSG msg;
    AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);

    SendMouseEvent(java_awt_event_MouseEvent_MOUSE_RELEASED, TimeHelper::getMessageTimeUTC(),
                   x, y, AwtComponent::GetJavaModifiers(), clickCount,
                   (AwtComponent::GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ?
                    TRUE : FALSE), AwtComponent::GetButton(button), &msg);

    if ((m_mouseButtonClickAllowed & AwtComponent::GetButtonMK(button)) != 0) { // No up-button in the drag-state
        SendMouseEvent(java_awt_event_MouseEvent_MOUSE_CLICKED,
                       TimeHelper::getMessageTimeUTC(), x, y, AwtComponent::GetJavaModifiers(),
                       clickCount, JNI_FALSE, AwtComponent::GetButton(button));
    }
    m_mouseButtonClickAllowed &= ~AwtComponent::GetButtonMK(button); // Exclude the up-button from the drag-state

    return mrConsume;
}

MsgRouting AwtTrayIcon::WmMouseMove(UINT flags, int x, int y)
{
    MSG msg;
    static AwtTrayIcon* lastComp = NULL;
    static int lastX = 0;
    static int lastY = 0;

    /*
     * Workaround for CR#6267980
     * Windows sends WM_MOUSEMOVE if mouse is motionless
     */
    if (lastComp != this || x != lastX || y != lastY) {
        lastComp = this;
        lastX = x;
        lastY = y;
        AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
        if ((flags & ALL_MK_BUTTONS) != 0) {
            m_mouseButtonClickAllowed = 0;
        } else {
            SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, TimeHelper::getMessageTimeUTC(), x, y,
                           AwtComponent::GetJavaModifiers(), 0, JNI_FALSE,
                           java_awt_event_MouseEvent_NOBUTTON, &msg);
        }
    }
    return mrConsume;
}

MsgRouting AwtTrayIcon::WmBalloonUserClick(UINT flags, int x, int y)
{
    if (AwtComponent::GetJavaModifiers() & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) {
        MSG msg;
        AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
        SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, TimeHelper::getMessageTimeUTC(),
                        AwtComponent::GetJavaModifiers(), &msg);
    }
    return mrConsume;
}

MsgRouting AwtTrayIcon::WmKeySelect(UINT flags, int x, int y)
{
    static jlong lastKeySelectTime = 0;
    jlong now = TimeHelper::getMessageTimeUTC();

    // If a user selects a notify icon with the ENTER key,
    // Shell 5.0 sends double NIN_KEYSELECT notification.
    if (lastKeySelectTime != now) {
        MSG msg;
        AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
        SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, TimeHelper::getMessageTimeUTC(),
                        AwtComponent::GetJavaModifiers(), &msg);
    }
    lastKeySelectTime = now;

    return mrConsume;
}

MsgRouting AwtTrayIcon::WmSelect(UINT flags, int x, int y)
{

    // If a user click on a notify icon with the mouse,
    // Shell 5.0 sends NIN_SELECT notification on every click.
    // To be compatible with JDK6.0 only second click is important.
    if (clickCount == 2) {
        MSG msg;
        AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
        SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, TimeHelper::getMessageTimeUTC(),
                        AwtComponent::GetJavaModifiers(), &msg);
    }
    return mrConsume;
}

MsgRouting AwtTrayIcon::WmContextMenu(UINT flags, int x, int y)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    jobject peer = GetPeer(env);
    if (peer != NULL) {
        JNU_CallMethodByName(env, NULL, peer, "showPopupMenu",
                             "(II)V", x, y);
    }
    return mrConsume;
}

/*
 * Adds all icons we already have to taskbar.
 * We use this method on taskbar recreation (see 6369062).
 */
MsgRouting AwtTrayIcon::WmTaskbarCreated() {
    TrayIconListItem* item;
    for (item = sm_trayIconList; item != NULL; item = item->m_next) {
        BOOL result = item->m_trayIcon->SendTrayMessage(NIM_ADD);
        // 6270114: Instructs the taskbar to behave according to the Shell version 5.0
        if (result) {
            item->m_trayIcon->SendTrayMessage(NIM_SETVERSION);
        }
    }
    return mrDoDefault;
}

void AwtTrayIcon::SendMouseEvent(jint id, jlong when, jint x, jint y,
                                 jint modifiers, jint clickCount,
                                 jboolean popupTrigger, jint button,
                                 MSG *pMsg)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    if (GetPeer(env) == NULL) {
        /* event received during termination. */
        return;
    }

    static jclass mouseEventCls;
    if (mouseEventCls == NULL) {
        jclass mouseEventClsLocal =
            env->FindClass("java/awt/event/MouseEvent");
        if (!mouseEventClsLocal) {
            /* exception already thrown */
            return;
        }
        mouseEventCls = (jclass)env->NewGlobalRef(mouseEventClsLocal);
        env->DeleteLocalRef(mouseEventClsLocal);
    }

    static jmethodID mouseEventConst;
    if (mouseEventConst == NULL) {
        mouseEventConst =
            env->GetMethodID(mouseEventCls, "<init>",
                             "(Ljava/awt/Component;IJIIIIIIZI)V");
        DASSERT(mouseEventConst);
        CHECK_NULL(mouseEventConst);
    }
    if (env->EnsureLocalCapacity(2) < 0) {
        return;
    }
    jobject target = GetTarget(env);
    jobject mouseEvent = env->NewObject(mouseEventCls, mouseEventConst,
                                        target,
                                        id, when, modifiers,
                                        x, y, // no client area coordinates
                                        x, y,
                                        clickCount, popupTrigger, button);

    if (safe_ExceptionOccurred(env)) {
        env->ExceptionDescribe();
        env->ExceptionClear();
    }

    DASSERT(mouseEvent != NULL);
    if (pMsg != 0) {
        AwtAWTEvent::saveMSG(env, pMsg, mouseEvent);
    }
    SendEvent(mouseEvent);

    env->DeleteLocalRef(mouseEvent);
    env->DeleteLocalRef(target);
}

void AwtTrayIcon::SendActionEvent(jint id, jlong when, jint modifiers, MSG *pMsg)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    if (GetPeer(env) == NULL) {
        /* event received during termination. */
        return;
    }

    static jclass actionEventCls;
    if (actionEventCls == NULL) {
        jclass actionEventClsLocal =
            env->FindClass("java/awt/event/ActionEvent");
        if (!actionEventClsLocal) {
            /* exception already thrown */
            return;
        }
        actionEventCls = (jclass)env->NewGlobalRef(actionEventClsLocal);
        env->DeleteLocalRef(actionEventClsLocal);
    }

    static jmethodID actionEventConst;
    if (actionEventConst == NULL) {
        actionEventConst =
            env->GetMethodID(actionEventCls, "<init>",
                             "(Ljava/lang/Object;ILjava/lang/String;JI)V");
        DASSERT(actionEventConst);
        CHECK_NULL(actionEventConst);
    }
    if (env->EnsureLocalCapacity(2) < 0) {
        return;
    }
    jobject target = GetTarget(env);
    jstring actionCommand = (jstring)env->GetObjectField(target, AwtTrayIcon::actionCommandID);
    jobject actionEvent = env->NewObject(actionEventCls, actionEventConst,
                                         target, id, actionCommand, when, modifiers);

    if (safe_ExceptionOccurred(env)) {
        env->ExceptionDescribe();
        env->ExceptionClear();
    }

    DASSERT(actionEvent != NULL);
    if (pMsg != 0) {
        AwtAWTEvent::saveMSG(env, pMsg, actionEvent);
    }
    SendEvent(actionEvent);

    env->DeleteLocalRef(actionEvent);
    env->DeleteLocalRef(target);
    env->DeleteLocalRef(actionCommand);
}

AwtTrayIcon* AwtTrayIcon::SearchTrayIconItem(UINT id) {
    TrayIconListItem* item;
    for (item = sm_trayIconList; item != NULL; item = item->m_next) {
        if (item->m_ID == id) {
            return item->m_trayIcon;
        }
    }
    /*
     * DASSERT(FALSE);
     * This should not be happend if all tray icons are recorded
     */
    return NULL;
}

void AwtTrayIcon::RemoveTrayIconItem(UINT id) {
    TrayIconListItem* item = sm_trayIconList;
    TrayIconListItem* lastItem = NULL;
    while (item != NULL) {
        if (item->m_ID == id) {
            if (lastItem == NULL) {
                sm_trayIconList = item->m_next;
            } else {
                lastItem->m_next = item->m_next;
            }
            item->m_next = NULL;
            DASSERT(item != NULL);
            delete item;
            return;
        }
        lastItem = item;
        item = item->m_next;
    }
}

void AwtTrayIcon::LinkObjects(JNIEnv *env, jobject peer)
{
    if (m_peerObject == NULL) {
        m_peerObject = env->NewGlobalRef(peer);
    }

    /* Bind JavaPeer -> C++*/
    JNI_SET_PDATA(peer, this);
}

void AwtTrayIcon::UnlinkObjects()
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    if (m_peerObject) {
        JNI_SET_PDATA(m_peerObject, static_cast<PDATA>(NULL));
        env->DeleteGlobalRef(m_peerObject);
        m_peerObject = NULL;
    }
}

HBITMAP AwtTrayIcon::CreateBMP(HWND hW,int* imageData,int nSS, int nW, int nH)
{
    Bitmapheader    bmhHeader = {0};
    HDC             hDC;
    char            *ptrImageData;
    HBITMAP         hbmpBitmap;
    HBITMAP         hBitmap;
    int             nNumChannels    = 4;

    if (!hW) {
        hW = ::GetDesktopWindow();
    }
    hDC = ::GetDC(hW);
    if (!hDC) {
        return NULL;
    }

    bmhHeader.bmiHeader.bV5Size              = sizeof(BITMAPV5HEADER);
    bmhHeader.bmiHeader.bV5Width             = nW;
    bmhHeader.bmiHeader.bV5Height            = -nH;
    bmhHeader.bmiHeader.bV5Planes            = 1;

    bmhHeader.bmiHeader.bV5BitCount          = 32;
    bmhHeader.bmiHeader.bV5Compression       = BI_BITFIELDS;

    // The following mask specification specifies a supported 32 BPP
    // alpha format for Windows XP.
    bmhHeader.bmiHeader.bV5RedMask   =  0x00FF0000;
    bmhHeader.bmiHeader.bV5GreenMask =  0x0000FF00;
    bmhHeader.bmiHeader.bV5BlueMask  =  0x000000FF;
    bmhHeader.bmiHeader.bV5AlphaMask =  0xFF000000;

    hbmpBitmap = ::CreateDIBSection(hDC, (BITMAPINFO*)&(bmhHeader),
                                    DIB_RGB_COLORS,
                                    (void**)&(ptrImageData),
                                    NULL, 0);
    int  *srcPtr = imageData;
    char *dstPtr = ptrImageData;
    if (!dstPtr) {
        ReleaseDC(hW, hDC);
        return NULL;
    }
    for (int nOutern = 0; nOutern < nH; nOutern++) {
        for (int nInner = 0; nInner < nSS; nInner++) {
            dstPtr[3] = (*srcPtr >> 0x18) & 0xFF;
            dstPtr[2] = (*srcPtr >> 0x10) & 0xFF;
            dstPtr[1] = (*srcPtr >> 0x08) & 0xFF;
            dstPtr[0] = *srcPtr & 0xFF;

            srcPtr++;
            dstPtr += nNumChannels;
        }
    }

    // convert it into DDB to make CustomCursor work on WIN95
    hBitmap = CreateDIBitmap(hDC,
                             (BITMAPINFOHEADER*)&bmhHeader,
                             CBM_INIT,
                             (void *)ptrImageData,
                             (BITMAPINFO*)&bmhHeader,
                             DIB_RGB_COLORS);

    ::DeleteObject(hbmpBitmap);
    ::ReleaseDC(hW, hDC);
//  ::GdiFlush();
    return hBitmap;
}

void AwtTrayIcon::SetToolTip(LPCTSTR tooltip)
{
    if (tooltip == NULL) {
        m_nid.szTip[0] = '\0';
    } else if (lstrlen(tooltip) >= TRAY_ICON_TOOLTIP_MAX_SIZE) {
        _tcsncpy(m_nid.szTip, tooltip, TRAY_ICON_TOOLTIP_MAX_SIZE);
        m_nid.szTip[TRAY_ICON_TOOLTIP_MAX_SIZE - 1] = '\0';
    } else {
        _tcscpy_s(m_nid.szTip, TRAY_ICON_TOOLTIP_MAX_SIZE, tooltip);
    }

    SendTrayMessage(NIM_MODIFY);
}

void AwtTrayIcon::_SetToolTip(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    SetToolTipStruct *sts = (SetToolTipStruct *)param;
    jobject self = sts->trayIcon;
    jstring jtooltip = sts->tooltip;
    AwtTrayIcon *trayIcon = NULL;
    LPCTSTR tooltipStr = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    trayIcon = (AwtTrayIcon *)pData;

    if (jtooltip == NULL) {
        trayIcon->SetToolTip(NULL);
        goto ret;
    }

    tooltipStr = JNU_GetStringPlatformChars(env, jtooltip, (jboolean *)NULL);
    if (env->ExceptionCheck()) goto ret;
    trayIcon->SetToolTip(tooltipStr);
    JNU_ReleaseStringPlatformChars(env, jtooltip, tooltipStr);
ret:
    env->DeleteGlobalRef(self);
    env->DeleteGlobalRef(jtooltip);
    delete sts;
}

void AwtTrayIcon::SetIcon(HICON hIcon)
{
    ::DestroyIcon(m_nid.hIcon);
    m_nid.hIcon = hIcon;
}

void AwtTrayIcon::_SetIcon(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    SetIconStruct *sis = (SetIconStruct *)param;
    jobject self = sis->trayIcon;
    HICON hIcon = sis->hIcon;
    AwtTrayIcon *trayIcon = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    trayIcon = (AwtTrayIcon *)pData;

    trayIcon->SetIcon(hIcon);

ret:
    env->DeleteGlobalRef(self);
    delete sis;
}

void AwtTrayIcon::_UpdateIcon(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    UpdateIconStruct *uis = (UpdateIconStruct *)param;
    jobject self = uis->trayIcon;
    jboolean jupdate = uis->update;
    AwtTrayIcon *trayIcon = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    trayIcon = (AwtTrayIcon *)pData;

    BOOL result = trayIcon->SendTrayMessage(jupdate == JNI_TRUE ? NIM_MODIFY : NIM_ADD);
    // 6270114: Instructs the taskbar to behave according to the Shell version 5.0
    if (result && jupdate == JNI_FALSE) {
        trayIcon->SendTrayMessage(NIM_SETVERSION);
    }
ret:
    env->DeleteGlobalRef(self);
    delete uis;
}

void AwtTrayIcon::DisplayMessage(LPCTSTR caption, LPCTSTR text, LPCTSTR msgType)
{
    m_nid.uFlags |= NIF_INFO;
    m_nid.uTimeout = 10000;

    if (lstrcmp(msgType, TEXT("ERROR")) == 0) {
        m_nid.dwInfoFlags = NIIF_ERROR;
    } else if (lstrcmp(msgType, TEXT("WARNING")) == 0) {
        m_nid.dwInfoFlags = NIIF_WARNING;
    } else if (lstrcmp(msgType, TEXT("INFO")) == 0) {
        m_nid.dwInfoFlags = NIIF_INFO;
    } else if (lstrcmp(msgType, TEXT("NONE")) == 0) {
        m_nid.dwInfoFlags = NIIF_NONE;
    } else {
        m_nid.dwInfoFlags = NIIF_NONE;
    }

    if (caption[0] == '\0') {
        m_nid.szInfoTitle[0] = '\0';

    } else if (lstrlen(caption) >= TRAY_ICON_BALLOON_TITLE_MAX_SIZE) {

        _tcsncpy(m_nid.szInfoTitle, caption, TRAY_ICON_BALLOON_TITLE_MAX_SIZE);
        m_nid.szInfoTitle[TRAY_ICON_BALLOON_TITLE_MAX_SIZE - 1] = '\0';

    } else {
        _tcscpy_s(m_nid.szInfoTitle, TRAY_ICON_BALLOON_TITLE_MAX_SIZE, caption);
    }

    if (text[0] == '\0') {
        m_nid.szInfo[0] = ' ';
        m_nid.szInfo[1] = '\0';

    } else if (lstrlen(text) >= TRAY_ICON_BALLOON_INFO_MAX_SIZE) {

        _tcsncpy(m_nid.szInfo, text, TRAY_ICON_BALLOON_INFO_MAX_SIZE);
        m_nid.szInfo[TRAY_ICON_BALLOON_INFO_MAX_SIZE - 1] = '\0';

    } else {
        _tcscpy_s(m_nid.szInfo, TRAY_ICON_BALLOON_INFO_MAX_SIZE, text);
    }

    SendTrayMessage(NIM_MODIFY);
    m_nid.uFlags &= ~NIF_INFO;
}

void AwtTrayIcon::_DisplayMessage(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    DisplayMessageStruct *dms = (DisplayMessageStruct *)param;
    jobject self = dms->trayIcon;
    jstring jcaption = dms->caption;
    jstring jtext = dms-> text;
    jstring jmsgType = dms->msgType;
    AwtTrayIcon *trayIcon = NULL;
    LPCTSTR captionStr = NULL;
    LPCTSTR textStr = NULL;
    LPCTSTR msgTypeStr = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    trayIcon = (AwtTrayIcon *)pData;

    captionStr = JNU_GetStringPlatformChars(env, jcaption, (jboolean *)NULL);
    if (env->ExceptionCheck()) goto ret;
    textStr = JNU_GetStringPlatformChars(env, jtext, (jboolean *)NULL);
    if (env->ExceptionCheck()) {
        JNU_ReleaseStringPlatformChars(env, jcaption, captionStr);
        goto ret;
    }
    msgTypeStr = JNU_GetStringPlatformChars(env, jmsgType, (jboolean *)NULL);
    if (env->ExceptionCheck()) {
        JNU_ReleaseStringPlatformChars(env, jcaption, captionStr);
        JNU_ReleaseStringPlatformChars(env, jtext, textStr);
        goto ret;
    }
    trayIcon->DisplayMessage(captionStr, textStr, msgTypeStr);

    JNU_ReleaseStringPlatformChars(env, jcaption, captionStr);
    JNU_ReleaseStringPlatformChars(env, jtext, textStr);
    JNU_ReleaseStringPlatformChars(env, jmsgType, msgTypeStr);
ret:
    env->DeleteGlobalRef(self);
    env->DeleteGlobalRef(jcaption);
    env->DeleteGlobalRef(jtext);
    env->DeleteGlobalRef(jmsgType);
    delete dms;
}

/************************************************************************
 * TrayIcon native methods
 */

extern "C" {

/*
 * Class:     java_awt_TrayIcon
 * Method:    initIDs
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_java_awt_TrayIcon_initIDs(JNIEnv *env, jclass cls)
{
    TRY;

    /* init field ids */
    AwtTrayIcon::idID = env->GetFieldID(cls, "id", "I");
    DASSERT(AwtTrayIcon::idID != NULL);
    CHECK_NULL(AwtTrayIcon::idID);

    AwtTrayIcon::actionCommandID = env->GetFieldID(cls, "actionCommand", "Ljava/lang/String;");
    DASSERT(AwtTrayIcon::actionCommandID != NULL);
    CHECK_NULL( AwtTrayIcon::actionCommandID);

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WTrayIconPeer
 * Method:    create
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WTrayIconPeer_create(JNIEnv *env, jobject self)
{
    TRY;

    AwtToolkit::CreateComponent(self, NULL,
                                (AwtToolkit::ComponentFactory)
                                AwtTrayIcon::Create);
    PDATA pData;
    JNI_CHECK_PEER_CREATION_RETURN(self);

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WTrayIconPeer
 * Method:    _dispose
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WTrayIconPeer__1dispose(JNIEnv *env, jobject self)
{
    TRY;

    AwtObject::_Dispose(self);

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WTrayIconPeer
 * Method:    _setToolTip
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WTrayIconPeer_setToolTip(JNIEnv *env, jobject self,
                                              jstring tooltip)
{
    TRY;

    SetToolTipStruct *sts = new SetToolTipStruct;
    sts->trayIcon = env->NewGlobalRef(self);
    if (tooltip != NULL) {
        sts->tooltip = (jstring)env->NewGlobalRef(tooltip);
    } else {
        sts->tooltip = NULL;
    }

    AwtToolkit::GetInstance().SyncCall(AwtTrayIcon::_SetToolTip, sts);
    // global ref and sts are deleted in _SetToolTip

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WTrayIconPeer
 * Method:    setNativeIcon
 * Signature: (I[B[IIIII)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WTrayIconPeer_setNativeIcon(JNIEnv *env, jobject self,
                                                 jintArray intRasterData, jbyteArray andMask,
                                                 jint nSS, jint nW, jint nH)
{
    TRY;

    int length = env->GetArrayLength(andMask);
    jbyte *andMaskPtr = new jbyte[length];

    env->GetByteArrayRegion(andMask, 0, length, andMaskPtr);

    HBITMAP hMask = ::CreateBitmap(nW, nH, 1, 1, (BYTE *)andMaskPtr);
//    ::GdiFlush();

    delete[] andMaskPtr;

    jint *intRasterDataPtr = NULL;
    HBITMAP hColor = NULL;
    try {
        intRasterDataPtr = (jint *)env->GetPrimitiveArrayCritical(intRasterData, 0);
        if (intRasterDataPtr == NULL) {
            ::DeleteObject(hMask);
            return;
        }
        hColor = AwtTrayIcon::CreateBMP(NULL, (int *)intRasterDataPtr, nSS, nW, nH);
    } catch (...) {
        if (intRasterDataPtr != NULL) {
            env->ReleasePrimitiveArrayCritical(intRasterData, intRasterDataPtr, 0);
        }
        ::DeleteObject(hMask);
        throw;
    }

    env->ReleasePrimitiveArrayCritical(intRasterData, intRasterDataPtr, 0);
    intRasterDataPtr = NULL;

    HICON hIcon = NULL;

    if (hMask && hColor) {
        ICONINFO icnInfo;
        memset(&icnInfo, 0, sizeof(ICONINFO));
        icnInfo.hbmMask = hMask;
        icnInfo.hbmColor = hColor;
        icnInfo.fIcon = TRUE;
        icnInfo.xHotspot = TRAY_ICON_X_HOTSPOT;
        icnInfo.yHotspot = TRAY_ICON_Y_HOTSPOT;

        hIcon = ::CreateIconIndirect(&icnInfo);
    }
    ::DeleteObject(hColor);
    ::DeleteObject(hMask);

    //////////////////////////////////////////

    SetIconStruct *sis = new SetIconStruct;
    sis->trayIcon = env->NewGlobalRef(self);
    sis->hIcon = hIcon;

    AwtToolkit::GetInstance().SyncCall(AwtTrayIcon::_SetIcon, sis);
    // global ref is deleted in _SetIcon

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WTrayIconPeer
 * Method:    updateNativeIcon
 * Signature: (Z)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WTrayIconPeer_updateNativeIcon(JNIEnv *env, jobject self,
                                                    jboolean doUpdate)
{
    TRY;

    UpdateIconStruct *uis = new UpdateIconStruct;
    uis->trayIcon = env->NewGlobalRef(self);
    uis->update = doUpdate;

    AwtToolkit::GetInstance().SyncCall(AwtTrayIcon::_UpdateIcon, uis);
    // global ref is deleted in _UpdateIcon

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WTrayIconPeer
 * Method:    displayMessage
 * Signature: ()V;
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WTrayIconPeer__1displayMessage(JNIEnv *env, jobject self,
    jstring caption, jstring text, jstring msgType)
{
    TRY;

    DisplayMessageStruct *dms = new DisplayMessageStruct;
    dms->trayIcon = env->NewGlobalRef(self);
    dms->caption = (jstring)env->NewGlobalRef(caption);
    dms->text = (jstring)env->NewGlobalRef(text);
    dms->msgType = (jstring)env->NewGlobalRef(msgType);

    AwtToolkit::GetInstance().SyncCall(AwtTrayIcon::_DisplayMessage, dms);
    // global ref is deleted in _DisplayMessage

    CATCH_BAD_ALLOC(NULL);
}

} /* extern "C" */
