summaryrefslogtreecommitdiffstats
path: root/lib/libUPnP/Neptune/Source/System/Win32/NptWin32MessageQueue.cpp
blob: 925849c631215384e49134c274f61b49c4c3e948 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/*****************************************************************
|
|      Neptune - Win32 Message Queue
|
|      (c) 2001-2008 Gilles Boccon-Gibod
|      Author: Gilles Boccon-Gibod (bok@bok.net)
|
****************************************************************/

/*----------------------------------------------------------------------
|       includes
+---------------------------------------------------------------------*/
#include "NptWin32MessageQueue.h"
#ifndef TARGET_WINDOWS_STORE
/*----------------------------------------------------------------------
|       platform adaptation
+---------------------------------------------------------------------*/
#if defined(_WIN32_WCE)
#define GetWindowLongPtr GetWindowLong
#define SetWindowLongPtr SetWindowLong
#endif

/*----------------------------------------------------------------------
|       constants
+---------------------------------------------------------------------*/
const int NPT_WIN32_MESSAGE_ID_BASE = WM_USER + 9200;

/*----------------------------------------------------------------------
|       NPT_Win32WindowMessageQueue
+---------------------------------------------------------------------*/
NPT_Win32WindowMessageQueue::NPT_Win32WindowMessageQueue()
{
    // create a hidden window to process our incoming messages
    WNDCLASS wclass;

    // compute a unique class name
    m_ClassName[0] = 'N';
    m_ClassName[1] = 'P';
    m_ClassName[2] = 'T';
    m_ClassName[3] = 'H';
    m_ClassName[4] = 'W';
    NPT_String tid = NPT_String::FromInteger(GetCurrentThreadId());
    for (unsigned int i=0; i<=tid.GetLength(); i++) {
        m_ClassName[5+i] = tid.GetChars()[i];        
    }

    // register a window class
    wclass.style         = 0;
    wclass.lpfnWndProc   = NPT_Win32WindowMessageQueue::WindowProcedure;
    wclass.cbClsExtra    = 0;
    wclass.cbWndExtra    = 0;
    wclass.hInstance     = GetModuleHandle(NULL);
    wclass.hIcon         = NULL;
    wclass.hCursor       = NULL;
    wclass.hbrBackground = NULL;
    wclass.lpszMenuName  = NULL;
    wclass.lpszClassName = m_ClassName;

    // register the class and ignore any error because we might
    // be registering the class more than once                  
    RegisterClass(&wclass);

    // create the hidden window
    m_WindowHandle = CreateWindow(
        wclass.lpszClassName, // pointer to registered class name 
        TEXT(""),             // pointer to window name 
        0,                    // window style 
        0,                    // horizontal position of window 
        0,                    // vertical position of window 
        0,                    // window width 
        0,                    // window height 
        NULL,                 // handle to parent or owner window 
        NULL,                 // handle to menu or child-window identifier 
        wclass.hInstance,     // handle to application instance 
        NULL);

    // set a pointer to ourself as user data */
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable: 4244) // we have to test for this because SetWindowLongPtr
                                // is incorrectly defined, so we'll get a C4244 warning
#endif // _MSC_VER
    if (m_WindowHandle) {
        SetWindowLongPtr(m_WindowHandle, GWLP_USERDATA, NPT_POINTER_TO_LONG(this));
    }
#if defined(_MSC_VER)
#pragma warning( pop )
#endif // _MSC_VER
    m_hInstance = wclass.hInstance;
}

/*----------------------------------------------------------------------
|       NPT_Win32WindowMessageQueue
+---------------------------------------------------------------------*/
NPT_Win32WindowMessageQueue::~NPT_Win32WindowMessageQueue() 
{
    // remove ourself as user data to ensure we're not called anymore
    SetWindowLongPtr(m_WindowHandle, GWLP_USERDATA, 0);

    // destroy the hidden window
    DestroyWindow(m_WindowHandle);

    // unregister the window class
    UnregisterClass(m_ClassName, m_hInstance);
}

/*----------------------------------------------------------------------
|       NPT_Win32WindowMessageQueue::WindowProcedure
+---------------------------------------------------------------------*/
LRESULT CALLBACK 
NPT_Win32WindowMessageQueue::WindowProcedure(HWND   window, 
                                             UINT   message,
                                             WPARAM wparam, 
                                             LPARAM lparam)
{
    // if it is a windows message, just pass it along
    if (message != (UINT) NPT_WIN32_MESSAGE_ID_BASE) {
        return DefWindowProc(window, message, wparam, lparam);
    }

    // dispatch the message to the handler
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable: 4312) // we have to test for this because GetWindowLongPtr
                                // is incorrectly defined, so we'll get a C4244 warning
#endif // _MSC_VER
    NPT_Win32WindowMessageQueue* queue = reinterpret_cast<NPT_Win32WindowMessageQueue *>(GetWindowLongPtr(window, GWLP_USERDATA));
#if defined(_MSC_VER)
#pragma warning( pop )  
#endif // _MSC_VER
    if (queue == NULL) {
        return 0; 
    }
    queue->HandleMessage(reinterpret_cast<NPT_Message*>(lparam),
        reinterpret_cast<NPT_MessageHandler*>(wparam));
    return 0;
}

/*----------------------------------------------------------------------
|       NPT_Win32WindowMessageQueue::PumpMessage
+---------------------------------------------------------------------*/
NPT_Result
NPT_Win32WindowMessageQueue::PumpMessage(NPT_Timeout)
{
    // you cannot pump messages on this type of queue, since they will
    // be pumped by the main windows message loop 
    return NPT_ERROR_NOT_SUPPORTED; 
}

/*----------------------------------------------------------------------
|       NPT_Win32WindowMessageQueue::QueueMessage
+---------------------------------------------------------------------*/
NPT_Result
NPT_Win32WindowMessageQueue::QueueMessage(NPT_Message*        message,
                                          NPT_MessageHandler* handler)
{
    int result;

    result = ::PostMessage(m_WindowHandle, 
        NPT_WIN32_MESSAGE_ID_BASE, 
        (WPARAM)handler, 
        (LPARAM)message);

    if (result == 0) return NPT_FAILURE;
    return NPT_SUCCESS;
}

/*----------------------------------------------------------------------
|       NPT_Win32WindowMessageQueue::HandleMessage
+---------------------------------------------------------------------*/
NPT_Result
NPT_Win32WindowMessageQueue::HandleMessage(NPT_Message*        message,
                                           NPT_MessageHandler* handler)
{
    NPT_Result result = NPT_FAILURE;

    if (message && handler) {
        result = handler->HandleMessage(message);
    }
    delete message;
    return result;
}

#endif // ! TARGET_WINDOWS_STORE