00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "lspdef.h"
00031 #include <windows.h>
00032
00033 #define STRSAFE_NO_DEPRECATE
00034 #include <strsafe.h>
00035
00036
00037
00038
00039
00040
00041
00042 #define PROVIDER_CLASS TEXT("Layered WS2 Provider 0x%08x")
00043 #define PROVIDER_CLASS_CHAR_LEN 32
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #define MAX_ASYNC_RETRIES 7
00054 #define ASYNC_TIMEOUT 500 // half a second
00055
00056 #pragma warning(disable:4127) // Disable conditional expression is constant warning
00057 #pragma warning(disable:4706) // Disable assignment within conditional warning (message pump)
00058
00059
00060
00061
00062
00063
00064 static DWORD WINAPI
00065 AsyncMsgHandler(
00066 LPVOID lpParameter
00067 );
00068
00069
00070 static LRESULT CALLBACK
00071 AsyncWndProc(
00072 HWND hwnd,
00073 UINT uMsg,
00074 WPARAM wParam,
00075 LPARAM lParam
00076 );
00077
00078
00079
00080
00081 static HANDLE WorkerThreadHandle = NULL;
00082 static HWND AsyncWindow = NULL;
00083 static TCHAR AsyncProviderClassName[ PROVIDER_CLASS_CHAR_LEN ];
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 int
00096 StopAsyncWindowManager(
00097 )
00098 {
00099 int rc,
00100 code;
00101
00102 if ( NULL != AsyncWindow )
00103 {
00104
00105 PostMessage( AsyncWindow, WM_DESTROY, 0, 0 );
00106
00107
00108 rc = WaitForSingleObject( WorkerThreadHandle, 10000 );
00109 if ( WAIT_TIMEOUT == rc )
00110 {
00111 dbgprint("StopAsyncWindowManager: Timed out waiting for async thread!");
00112 goto cleanup;
00113 }
00114
00115
00116 rc = GetExitCodeThread( WorkerThreadHandle, (LPDWORD) &code );
00117 if ( 0 == rc )
00118 dbgprint("StopAsyncWindowManager: Unable to retrieve thread exit code: %d",
00119 GetLastError() );
00120 else if ( 0 != code )
00121 dbgprint("StopAsyncWindowManager: Async window thread exited abnormally!");
00122
00123 cleanup:
00124
00125 CloseHandle( WorkerThreadHandle );
00126
00127 WorkerThreadHandle = NULL;
00128 }
00129
00130 return 0;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 HWND
00142 GetWorkerWindow(
00143 )
00144 {
00145 HANDLE ReadyEvent = NULL;
00146 int rc;
00147
00148 EnterCriticalSection( &gCriticalSection );
00149 if ( NULL == WorkerThreadHandle )
00150 {
00151
00152 ReadyEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
00153 if ( NULL == ReadyEvent )
00154 {
00155 dbgprint("GetWorkerWindow: CreateEvent failed: %d", GetLastError() );
00156 goto cleanup;
00157 }
00158
00159
00160 WorkerThreadHandle = CreateThread(
00161 NULL,
00162 0,
00163 AsyncMsgHandler,
00164 (LPVOID)ReadyEvent,
00165 0,
00166 NULL
00167 );
00168 if ( NULL == WorkerThreadHandle )
00169 {
00170 dbgprint( "GetWorkerWindow: CreateThread failed: %d", GetLastError() );
00171 goto cleanup;
00172 }
00173
00174
00175 rc = WaitForSingleObject( ReadyEvent, INFINITE );
00176 if ( ( WAIT_FAILED == rc ) || ( WAIT_TIMEOUT == rc ) )
00177 dbgprint( "GetWorkerWindow: WaitForSingleObject failed: %d! (error = %d)",
00178 rc, GetLastError() );
00179 }
00180
00181 cleanup:
00182
00183 if ( NULL != ReadyEvent )
00184 {
00185
00186 rc = CloseHandle( ReadyEvent );
00187 if ( 0 == rc )
00188 {
00189 dbgprint("GetWorkerWindow: CloseHandle failed: %d", GetLastError() );
00190 }
00191 }
00192
00193 LeaveCriticalSection( &gCriticalSection );
00194
00195 return AsyncWindow;
00196 }
00197
00198
00199
00200
00201
00202
00203
00204 static DWORD WINAPI
00205 AsyncMsgHandler(
00206 LPVOID lpParameter
00207 )
00208 {
00209 MSG msg;
00210 DWORD Ret;
00211 HANDLE readyEvent;
00212 HRESULT hr;
00213 WNDCLASS wndclass;
00214
00215
00216
00217 readyEvent = (HANDLE) lpParameter;
00218
00219 hr = StringCchPrintf(
00220 AsyncProviderClassName,
00221 PROVIDER_CLASS_CHAR_LEN,
00222 PROVIDER_CLASS,
00223 GetCurrentProcessId()
00224 );
00225 if ( FAILED( hr ) )
00226 {
00227 dbgprint("AsyncMsgHandler: StringCchPrintf failed: %d", GetLastError());
00228 goto cleanup;
00229 }
00230
00231 dbgprint("AsyncMsgHandler: Class name is '%s'", AsyncProviderClassName );
00232
00233 memset( &wndclass, 0, sizeof( wndclass ) );
00234 wndclass.lpfnWndProc = (WNDPROC)AsyncWndProc;
00235 wndclass.hInstance = gDllInstance;
00236 wndclass.lpszClassName = AsyncProviderClassName;
00237
00238 if ( 0 == RegisterClass( &wndclass ) )
00239 {
00240 dbgprint("AsyncMsgHandle: RegisterClass failed: %d", GetLastError());
00241 goto cleanup;
00242 }
00243
00244
00245 AsyncWindow = CreateWindow(
00246 AsyncProviderClassName,
00247 TEXT("Layered Hidden Window"),
00248 WS_OVERLAPPEDWINDOW,
00249 CW_USEDEFAULT,
00250 CW_USEDEFAULT,
00251 CW_USEDEFAULT,
00252 CW_USEDEFAULT,
00253 NULL,
00254 NULL,
00255 gDllInstance,
00256 NULL
00257 );
00258
00259 if ( NULL == AsyncWindow )
00260 {
00261 dbgprint("AsyncMessageHandler: CreateWindow failed: %d", GetLastError() );
00262 goto cleanup;
00263 }
00264
00265
00266 SetEvent( readyEvent );
00267
00268
00269 while ( ( Ret = GetMessage( &msg, NULL, 0, 0 ) ) )
00270 {
00271 if ( -1 == Ret )
00272 {
00273 dbgprint("AsyncMessageHandler: GetMessage returned -1, exiting loop");
00274 break;
00275 }
00276 TranslateMessage( &msg );
00277 DispatchMessage( &msg );
00278 }
00279
00280
00281 if ( NULL != AsyncWindow )
00282 {
00283 DestroyWindow( AsyncWindow );
00284 AsyncWindow = NULL;
00285 }
00286
00287 UnregisterClass( AsyncProviderClassName, gDllInstance );
00288
00289 ExitThread(0);
00290
00291 cleanup:
00292
00293 SetEvent( readyEvent );
00294
00295 ExitThread( (DWORD) -1);
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306 static LRESULT CALLBACK
00307 AsyncWndProc(
00308 HWND hWnd,
00309 UINT uMsg,
00310 WPARAM wParam,
00311 LPARAM lParam
00312 )
00313 {
00314 SOCK_INFO *si = NULL;
00315 int retries,
00316 rc;
00317
00318 if ( WM_SOCKET == uMsg )
00319 {
00320 retries = 0;
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 while ( retries < MAX_ASYNC_RETRIES )
00333 {
00334 dbgprint("hWnd 0x%p, uMsg 0x%x, WPARAM 0x%p, LPARAM 0x%p (retries %d)",
00335 hWnd, uMsg, wParam, lParam, retries);
00336
00337
00338 si = GetCallerSocket( NULL, wParam );
00339 if ( NULL == si )
00340 {
00341 dbgprint("Unable to find socket context for 0x%p", wParam);
00342
00343
00344 rc = WaitForSingleObject( gAddContextEvent, ASYNC_TIMEOUT );
00345 if ( WAIT_FAILED == rc )
00346 {
00347 dbgprint("AsyncWndProc: WaitForSingleObject failed: %d",
00348 GetLastError());
00349 break;
00350 }
00351 else
00352 {
00353
00354 if ( WAIT_OBJECT_0 == rc )
00355 ResetEvent( gAddContextEvent );
00356
00357
00358 retries++;
00359 continue;
00360 }
00361 }
00362
00363 gMainUpCallTable.lpWPUPostMessage(
00364 si->hWnd,
00365 si->uMsg,
00366 si->LayeredSocket,
00367 lParam
00368 );
00369
00370 return 0;
00371 }
00372 }
00373 else if ( WM_DESTROY == uMsg )
00374 {
00375
00376 PostQuitMessage( 0 );
00377 return 0;
00378 }
00379
00380 return DefWindowProc( hWnd, uMsg, wParam, lParam );
00381 }