ReactOS 0.4.15-dev-8339-g4028de8
dplayx_messages.c
Go to the documentation of this file.
1/* DirectPlay & DirectPlayLobby messaging implementation
2 *
3 * Copyright 2000,2001 - Peter Hunnisett
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 *
19 * NOTES
20 * o Messaging interface required for both DirectPlay and DirectPlayLobby.
21 */
22
23#include <stdarg.h>
24#include <string.h>
25#include "windef.h"
26#include "winbase.h"
27#include "wingdi.h"
28#include "winuser.h"
29#include "winerror.h"
30
31#include "dplayx_messages.h"
32#include "dplay_global.h"
33#include "dplayx_global.h"
34#include "name_server.h"
35#include "wine/debug.h"
36
38
39typedef struct tagMSGTHREADINFO
40{
46
47static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext );
49 WORD wReplyCommandId, void **lplpReplyMsg, DWORD *lpdwMsgBodySize );
50
51
52/* Create the message reception thread to allow the application to receive
53 * asynchronous message reception
54 */
56 HANDLE hDeath, HANDLE hConnRead )
57{
58 DWORD dwMsgThreadId;
59 LPMSGTHREADINFO lpThreadInfo;
61
62 lpThreadInfo = HeapAlloc( GetProcessHeap(), 0, sizeof( *lpThreadInfo ) );
63 if( lpThreadInfo == NULL )
64 {
65 return 0;
66 }
67
68 /* The notify event may or may not exist. Depends if async comm or not */
69 if( hNotifyEvent &&
70 !DuplicateHandle( GetCurrentProcess(), hNotifyEvent,
71 GetCurrentProcess(), &lpThreadInfo->hNotifyEvent,
73 {
74 ERR( "Unable to duplicate event handle\n" );
75 goto error;
76 }
77
78 /* These 3 handles don't need to be duplicated because we don't keep a
79 * reference to them where they're created. They're created specifically
80 * for the message thread
81 */
82 lpThreadInfo->hStart = hStart;
83 lpThreadInfo->hDeath = hDeath;
84 lpThreadInfo->hSettingRead = hConnRead;
85
86 hThread = CreateThread( NULL, /* Security attribs */
87 0, /* Stack */
88 DPL_MSG_ThreadMain, /* Msg reception function */
89 lpThreadInfo, /* Msg reception func parameter */
90 0, /* Flags */
91 &dwMsgThreadId /* Updated with thread id */
92 );
93 if ( hThread == NULL )
94 {
95 ERR( "Unable to create msg thread\n" );
96 goto error;
97 }
98
100
101 return dwMsgThreadId;
102
103error:
104
105 HeapFree( GetProcessHeap(), 0, lpThreadInfo );
106
107 return 0;
108}
109
111{
112 LPMSGTHREADINFO lpThreadInfo = lpContext;
113 DWORD dwWaitResult;
114
115 TRACE( "Msg thread created. Waiting on app startup\n" );
116
117 /* Wait to ensure that the lobby application is started w/ 1 min timeout */
118 dwWaitResult = WaitForSingleObject( lpThreadInfo->hStart, 10000 /* 10 sec */ );
119 if( dwWaitResult == WAIT_TIMEOUT )
120 {
121 FIXME( "Should signal app/wait creation failure (0x%08x)\n", dwWaitResult );
122 goto end_of_thread;
123 }
124
125 /* Close this handle as it's not needed anymore */
126 CloseHandle( lpThreadInfo->hStart );
127 lpThreadInfo->hStart = 0;
128
129 /* Wait until the lobby knows what it is */
130 dwWaitResult = WaitForSingleObject( lpThreadInfo->hSettingRead, INFINITE );
131 if( dwWaitResult == WAIT_TIMEOUT )
132 {
133 ERR( "App Read connection setting timeout fail (0x%08x)\n", dwWaitResult );
134 }
135
136 /* Close this handle as it's not needed anymore */
137 CloseHandle( lpThreadInfo->hSettingRead );
138 lpThreadInfo->hSettingRead = 0;
139
140 TRACE( "App created && initialized starting main message reception loop\n" );
141
142 for ( ;; )
143 {
144 MSG lobbyMsg;
145 GetMessageW( &lobbyMsg, 0, 0, 0 );
146 }
147
148end_of_thread:
149 TRACE( "Msg thread exiting!\n" );
150 HeapFree( GetProcessHeap(), 0, lpThreadInfo );
151
152 return 0;
153}
154
155/* DP messaging stuff */
157 DP_MSG_REPLY_STRUCT_LIST *lpReplyStructList, WORD wReplyCommandId )
158{
159 lpReplyStructList->replyExpected.hReceipt = CreateEventW( NULL, FALSE, FALSE, NULL );
160 lpReplyStructList->replyExpected.wExpectedReply = wReplyCommandId;
161 lpReplyStructList->replyExpected.lpReplyMsg = NULL;
162 lpReplyStructList->replyExpected.dwMsgBodySize = 0;
163
164 /* Insert into the message queue while locked */
165 EnterCriticalSection( &This->lock );
166 DPQ_INSERT( This->dp2->repliesExpected, lpReplyStructList, repliesExpected );
167 LeaveCriticalSection( &This->lock );
168
169 return lpReplyStructList->replyExpected.hReceipt;
170}
171
172static
174 LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize )
175{
176 CloseHandle( lpReplyStructList->replyExpected.hReceipt );
177
178 *lplpReplyMsg = lpReplyStructList->replyExpected.lpReplyMsg;
179 *lpdwMsgBodySize = lpReplyStructList->replyExpected.dwMsgBodySize;
180
181 return lpReplyStructList->replyExpected.lpReplyMsg;
182}
183
185{
186 LPVOID lpMsg;
188 DWORD dwMsgSize;
189 HRESULT hr = DP_OK;
190
191 dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody );
192
193 lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize );
194
195 lpMsgBody = (LPDPMSG_REQUESTNEWPLAYERID)( (BYTE*)lpMsg +
196 This->dp2->spData.dwSPHeaderSize );
197
198 /* Compose dplay message envelope */
201 lpMsgBody->envelope.wVersion = DPMSGVER_DP6;
202
203 /* Compose the body of the message */
204 lpMsgBody->dwFlags = dwFlags;
205
206 /* Send the message */
207 {
209
210 data.dwFlags = DPSEND_GUARANTEED;
211 data.idPlayerTo = 0; /* Name server */
212 data.idPlayerFrom = 0; /* Sending from DP */
213 data.lpMessage = lpMsg;
214 data.dwMessageSize = dwMsgSize;
215 data.bSystemMessage = TRUE; /* Allow reply to be sent */
216 data.lpISP = This->dp2->spData.lpISP;
217
218 TRACE( "Asking for player id w/ dwFlags 0x%08x\n",
219 lpMsgBody->dwFlags );
220
222 &lpMsg, &dwMsgSize );
223 }
224
225 /* Need to examine the data and extract the new player id */
226 if( SUCCEEDED(hr) )
227 {
229
230 lpcReply = lpMsg;
231
232 *lpdpidAllocatedId = lpcReply->dpidNewPlayerId;
233
234 TRACE( "Received reply for id = 0x%08x\n", lpcReply->dpidNewPlayerId );
235
236 /* FIXME: I think that the rest of the message has something to do
237 * with remote data for the player that perhaps I need to setup.
238 * However, with the information that is passed, all that it could
239 * be used for is a standardized initialization value, which I'm
240 * guessing we can do without. Unless the message content is the same
241 * for several different messages?
242 */
243
244 HeapFree( GetProcessHeap(), 0, lpMsg );
245 }
246
247 return hr;
248}
249
251{
252 LPVOID lpMsg;
253 LPDPMSG_FORWARDADDPLAYER lpMsgBody;
254 DWORD dwMsgSize;
255 HRESULT hr = DP_OK;
256
257 dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody );
258
259 lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize );
260
261 lpMsgBody = (LPDPMSG_FORWARDADDPLAYER)( (BYTE*)lpMsg +
262 This->dp2->spData.dwSPHeaderSize );
263
264 /* Compose dplay message envelope */
267 lpMsgBody->envelope.wVersion = DPMSGVER_DP6;
268
269#if 0
270 {
271 LPBYTE lpPData;
272 DWORD dwDataSize;
273
274 /* SP Player remote data needs to be propagated at some point - is this the point? */
275 IDirectPlaySP_GetSPPlayerData( This->dp2->spData.lpISP, 0, &lpPData, &dwDataSize, DPSET_REMOTE );
276
277 ERR( "Player Data size is 0x%08lx\n"
278 "[%02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x]\n"
279 "[%02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x]\n",
280
281 dwDataSize,
282 lpPData[0], lpPData[1], lpPData[2], lpPData[3], lpPData[4],
283 lpPData[5], lpPData[6], lpPData[7], lpPData[8], lpPData[9],
284 lpPData[10], lpPData[11], lpPData[12], lpPData[13], lpPData[14],
285 lpPData[15], lpPData[16], lpPData[17], lpPData[18], lpPData[19],
286 lpPData[20], lpPData[21], lpPData[22], lpPData[23], lpPData[24],
287 lpPData[25], lpPData[26], lpPData[27], lpPData[28], lpPData[29],
288 lpPData[30], lpPData[31]
289 );
290 DebugBreak();
291 }
292#endif
293
294 /* Compose body of message */
295 lpMsgBody->dpidAppServer = dpidServer;
296 lpMsgBody->unknown2[0] = 0x0;
297 lpMsgBody->unknown2[1] = 0x1c;
298 lpMsgBody->unknown2[2] = 0x6c;
299 lpMsgBody->unknown2[3] = 0x50;
300 lpMsgBody->unknown2[4] = 0x9;
301
302 lpMsgBody->dpidAppServer2 = dpidServer;
303 lpMsgBody->unknown3[0] = 0x0;
304 lpMsgBody->unknown3[1] = 0x0;
305 lpMsgBody->unknown3[2] = 0x20;
306 lpMsgBody->unknown3[3] = 0x0;
307 lpMsgBody->unknown3[4] = 0x0;
308
309 lpMsgBody->dpidAppServer3 = dpidServer;
310 lpMsgBody->unknown4[0] = 0x30;
311 lpMsgBody->unknown4[1] = 0xb;
312 lpMsgBody->unknown4[2] = 0x0;
313
314 lpMsgBody->unknown4[3] = NS_GetNsMagic( This->dp2->lpNameServerData ) -
315 0x02000000;
316 TRACE( "Setting first magic to 0x%08x\n", lpMsgBody->unknown4[3] );
317
318 lpMsgBody->unknown4[4] = 0x0;
319 lpMsgBody->unknown4[5] = 0x0;
320 lpMsgBody->unknown4[6] = 0x0;
321
322 lpMsgBody->unknown4[7] = NS_GetNsMagic( This->dp2->lpNameServerData );
323 TRACE( "Setting second magic to 0x%08x\n", lpMsgBody->unknown4[7] );
324
325 lpMsgBody->unknown4[8] = 0x0;
326 lpMsgBody->unknown4[9] = 0x0;
327 lpMsgBody->unknown4[10] = 0x0;
328 lpMsgBody->unknown4[11] = 0x0;
329
330 lpMsgBody->unknown5[0] = 0x0;
331 lpMsgBody->unknown5[1] = 0x0;
332
333 /* Send the message */
334 {
336
337 data.dwFlags = DPSEND_GUARANTEED;
338 data.idPlayerTo = 0; /* Name server */
339 data.idPlayerFrom = dpidServer; /* Sending from session server */
340 data.lpMessage = lpMsg;
341 data.dwMessageSize = dwMsgSize;
342 data.bSystemMessage = TRUE; /* Allow reply to be sent */
343 data.lpISP = This->dp2->spData.lpISP;
344
345 TRACE( "Sending forward player request with 0x%08x\n", dpidServer );
346
347 lpMsg = DP_MSG_ExpectReply( This, &data,
350 &lpMsg, &dwMsgSize );
351 }
352
353 /* Need to examine the data and extract the new player id */
354 if( lpMsg != NULL )
355 {
356 FIXME( "Name Table reply received: stub\n" );
357 }
358
359 return hr;
360}
361
362/* Queue up a structure indicating that we want a reply of type wReplyCommandId. DPlay does
363 * not seem to offer any way of uniquely differentiating between replies of the same type
364 * relative to the request sent. There is an implicit assumption that there will be no
365 * ordering issues on sends and receives from the opposite machine. No wonder MS is not
366 * a networking company.
367 */
368static void *DP_MSG_ExpectReply( IDirectPlayImpl *This, DPSP_SENDDATA *lpData, DWORD dwWaitTime,
369 WORD wReplyCommandId, void **lplpReplyMsg, DWORD *lpdwMsgBodySize )
370{
371 HRESULT hr;
372 HANDLE hMsgReceipt;
373 DP_MSG_REPLY_STRUCT_LIST replyStructList;
374 DWORD dwWaitReturn;
375
376 /* Setup for receipt */
377 hMsgReceipt = DP_MSG_BuildAndLinkReplyStruct( This, &replyStructList,
378 wReplyCommandId );
379
380 TRACE( "Sending msg and expecting cmd %u in reply within %u ticks\n",
381 wReplyCommandId, dwWaitTime );
382 hr = (*This->dp2->spData.lpCB->Send)( lpData );
383
384 if( FAILED(hr) )
385 {
386 ERR( "Send failed: %s\n", DPLAYX_HresultToString( hr ) );
387 return NULL;
388 }
389
390 /* The reply message will trigger the hMsgReceipt event effectively switching
391 * control back to this thread. See DP_MSG_ReplyReceived.
392 */
393 dwWaitReturn = WaitForSingleObject( hMsgReceipt, dwWaitTime );
394 if( dwWaitReturn != WAIT_OBJECT_0 )
395 {
396 ERR( "Wait failed 0x%08x\n", dwWaitReturn );
397 return NULL;
398 }
399
400 /* Clean Up */
401 return DP_MSG_CleanReplyStruct( &replyStructList, lplpReplyMsg, lpdwMsgBodySize );
402}
403
404/* Determine if there is a matching request for this incoming message and then copy
405 * all important data. It is quite silly to have to copy the message, but the documents
406 * indicate that a copy is taken. Silly really.
407 */
408void DP_MSG_ReplyReceived( IDirectPlayImpl *This, WORD wCommandId, const void *lpcMsgBody,
409 DWORD dwMsgBodySize )
410{
411 LPDP_MSG_REPLY_STRUCT_LIST lpReplyList;
412
413#if 0
414 if( wCommandId == DPMSGCMD_FORWARDADDPLAYER )
415 {
416 DebugBreak();
417 }
418#endif
419
420 /* Find, and immediately remove (to avoid double triggering), the appropriate entry. Call locked to
421 * avoid problems.
422 */
423 EnterCriticalSection( &This->lock );
424 DPQ_REMOVE_ENTRY( This->dp2->repliesExpected, repliesExpected, replyExpected.wExpectedReply,
425 ==, wCommandId, lpReplyList );
426 LeaveCriticalSection( &This->lock );
427
428 if( lpReplyList != NULL )
429 {
430 lpReplyList->replyExpected.dwMsgBodySize = dwMsgBodySize;
433 dwMsgBodySize );
434 CopyMemory( lpReplyList->replyExpected.lpReplyMsg,
435 lpcMsgBody, dwMsgBodySize );
436
437 /* Signal the thread which sent the message that it has a reply */
438 SetEvent( lpReplyList->replyExpected.hReceipt );
439 }
440 else
441 {
442 ERR( "No receipt event set - only expecting in reply mode\n" );
443 DebugBreak();
444 }
445}
446
448{
449 LPVOID lpMsg;
450 LPDPMSG_SENDENVELOPE lpMsgBody;
451 DWORD dwMsgSize;
452
453 dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody );
454
455 lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize );
456
457 lpMsgBody = (LPDPMSG_SENDENVELOPE)( (BYTE*)lpMsg +
458 This->dp2->spData.dwSPHeaderSize );
459
460 /* Compose dplay message envelope */
461 lpMsgBody->dwMagic = DPMSGMAGIC_DPLAYMSG;
463 lpMsgBody->wVersion = DPMSGVER_DP6;
464
465 /* Send the message to ourselves */
466 {
468
469 data.dwFlags = 0;
470 data.idPlayerTo = dpidSelf; /* Sending to session server */
471 data.idPlayerFrom = 0; /* Sending from session server */
472 data.lpMessage = lpMsg;
473 data.dwMessageSize = dwMsgSize;
474 data.bSystemMessage = TRUE; /* Allow reply to be sent */
475 data.lpISP = This->dp2->spData.lpISP;
476
477 lpMsg = DP_MSG_ExpectReply( This, &data,
480 &lpMsg, &dwMsgSize );
481 }
482}
483
484void DP_MSG_ErrorReceived( IDirectPlayImpl *This, WORD wCommandId, const void *lpMsgBody,
485 DWORD dwMsgBodySize )
486{
488
489 lpcErrorMsg = lpMsgBody;
490
491 ERR( "Received error message %u. Error is %s\n",
492 wCommandId, DPLAYX_HresultToString( lpcErrorMsg->errorCode) );
493 DebugBreak();
494}
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define FIXME(fmt,...)
Definition: precomp.h:53
#define ERR(fmt,...)
Definition: precomp.h:57
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define GetCurrentProcess()
Definition: compat.h:759
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CALLBACK
Definition: compat.h:35
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
BOOL WINAPI DuplicateHandle(IN HANDLE hSourceProcessHandle, IN HANDLE hSourceHandle, IN HANDLE hTargetProcessHandle, OUT LPHANDLE lpTargetHandle, IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwOptions)
Definition: handle.c:149
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
#define DPSET_REMOTE
Definition: dplay.h:1056
#define DPSEND_GUARANTEED
Definition: dplay.h:1038
#define DP_OK
Definition: dplay.h:88
DWORD DPID
Definition: dplay.h:158
#define IDirectPlaySP_GetSPPlayerData(p, a, b, c, d)
Definition: dplaysp.h:104
LPCSTR DPLAYX_HresultToString(HRESULT hr)
void DP_MSG_ErrorReceived(IDirectPlayImpl *This, WORD wCommandId, const void *lpMsgBody, DWORD dwMsgBodySize)
struct tagMSGTHREADINFO * LPMSGTHREADINFO
struct tagMSGTHREADINFO MSGTHREADINFO
static void * DP_MSG_ExpectReply(IDirectPlayImpl *This, DPSP_SENDDATA *data, DWORD dwWaitTime, WORD wReplyCommandId, void **lplpReplyMsg, DWORD *lpdwMsgBodySize)
void DP_MSG_ReplyReceived(IDirectPlayImpl *This, WORD wCommandId, const void *lpcMsgBody, DWORD dwMsgBodySize)
DWORD CreateLobbyMessageReceptionThread(HANDLE hNotifyEvent, HANDLE hStart, HANDLE hDeath, HANDLE hConnRead)
void DP_MSG_ToSelf(IDirectPlayImpl *This, DPID dpidSelf)
static HANDLE DP_MSG_BuildAndLinkReplyStruct(IDirectPlayImpl *This, DP_MSG_REPLY_STRUCT_LIST *lpReplyStructList, WORD wReplyCommandId)
HRESULT DP_MSG_SendRequestPlayerId(IDirectPlayImpl *This, DWORD dwFlags, DPID *lpdpidAllocatedId)
static LPVOID DP_MSG_CleanReplyStruct(LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList, LPVOID *lplpReplyMsg, LPDWORD lpdwMsgBodySize)
static DWORD CALLBACK DPL_MSG_ThreadMain(LPVOID lpContext)
HRESULT DP_MSG_ForwardPlayerCreation(IDirectPlayImpl *This, DPID dpidServer)
#define DPMSGVER_DP6
struct tagDPMSG_REQUESTNEWPLAYERID * LPDPMSG_REQUESTNEWPLAYERID
#define DPMSGCMD_GETNAMETABLEREPLY
#define DPMSG_WAIT_5_SECS
struct tagDPMSG_SENDENVELOPE * LPDPMSG_SENDENVELOPE
#define DPMSGCMD_FORWARDADDPLAYER
#define DPMSGCMD_REQUESTNEWPLAYERID
#define DPMSGCMD_NEWPLAYERIDREPLY
#define DPMSG_WAIT_60_SECS
#define DPMSGCMD_JUSTENVELOPE
#define DPMSGMAGIC_DPLAYMSG
struct tagDPMSG_FORWARDADDPLAYER * LPDPMSG_FORWARDADDPLAYER
#define DPMSG_DEFAULT_WAIT_TIME
#define DPQ_REMOVE_ENTRY(head, elm, field, fieldCompareOperator, fieldToCompare, rc)
Definition: dplayx_queue.h:162
#define DPQ_INSERT(a, b, c)
Definition: dplayx_queue.h:34
#define INFINITE
Definition: serial.h:102
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define error(str)
Definition: mkdosfs.c:1605
DWORD NS_GetNsMagic(LPVOID lpNSInfo)
Definition: name_server.c:177
HANDLE hThread
Definition: wizard.c:28
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
DPMSG_SENDENVELOPE envelope
DPMSG_SENDENVELOPE envelope
DP_MSG_REPLY_STRUCT replyExpected
Definition: dplay_global.h:55
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
unsigned char * LPBYTE
Definition: typedefs.h:53
uint32_t * LPDWORD
Definition: typedefs.h:59
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI DebugBreak(void)
#define CopyMemory
Definition: winbase.h:1710
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define WAIT_OBJECT_0
Definition: winbase.h:406
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
BOOL WINAPI GetMessageW(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT)
#define DUPLICATE_SAME_ACCESS
unsigned char BYTE
Definition: xxhash.c:193