1 /* AbiSource Program Utilities
2  * Copyright (C) 2003 Tomas Frydrych <tomas@frydrych.uklinux.net>
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301 USA.
18  */
19 
20 #include "ut_misc.h"
21 #include <windows.h>
22 #ifdef _MSC_VER
23 #include <winsock.h>
24 #else
25 #include <mswsock.h>
26 #endif
27 #ifndef __WINE__
28 #include <snmp.h>
29 #endif
30 #include <nb30.h>
31 #include <stdio.h>
32 #include "ut_debugmsg.h"
33 #include "ut_Win32Resources.rc2"
34 #include "ut_Win32Timer.h"
35 #include "ut_Win32LocaleString.h"
36 
37 /*!
38     UT_gettimeofday() fills in the timeval structure with current
39     time; the platform implementation needs to be as accurate as
40     possible since this function is used in the UT_UUID class.
41 
42     this implementation is from:
43     http://bugzilla.vovida.org/bugzilla/show_bug.cgi?id=751
44  */
UT_gettimeofday(struct timeval * tv)45 void UT_gettimeofday(struct timeval *tv)
46 {
47     FILETIME ft;
48     GetSystemTimeAsFileTime (&ft);
49 
50     ULARGE_INTEGER _100ns = {{ft.dwLowDateTime,ft.dwHighDateTime}};
51 
52 #ifndef __GNUC__
53     _100ns.QuadPart -= 0x19db1ded53e8000;
54 #else
55     _100ns.QuadPart -= 0x19db1ded53e8000ULL;
56 #endif
57     tv->tv_sec = long (_100ns.QuadPart / (10000 * 1000));
58     tv->tv_usec = (long) ((_100ns.LowPart % (DWORD) (10000 * 1000)) / 10);
59 }
60 
61 #ifndef __WINE__
62 #define NO_MAC_ADDRESS
63 #endif
64 #ifdef NO_MAC_ADDRESS
65 typedef struct _ASTAT
66 {
67 	ADAPTER_STATUS adapt;
68 	NAME_BUFFER    NameBuff [30];
69 }ASTAT, * PASTAT;
70 
71 typedef BOOL(WINAPI * pSnmpExtensionInit) (IN DWORD dwTimeZeroReference,
72 										   OUT HANDLE * hPollForTrapEvent,
73 										   OUT AsnObjectIdentifier * supportedView);
74 
75 typedef BOOL(WINAPI * pSnmpExtensionQuery) (IN BYTE requestType,
76 											IN OUT RFC1157VarBindList * variableBindings,
77 											OUT AsnInteger * errorStatus,
78 											OUT AsnInteger * errorIndex);
79 
80 typedef VOID (WINAPI * pSnmpUtilVarBindFree) (RFC1157VarBind *VarBind);
81 
82 typedef SNMPAPI (WINAPI * pSnmpUtilOidNCmp )(AsnObjectIdentifier *ObjIdA,
83 											 AsnObjectIdentifier *ObjIdB,
84 											 UINT Len);
85 
86 typedef SNMPAPI (WINAPI * pSnmpUtilOidCpy) (AsnObjectIdentifier *DestObjId,
87 											AsnObjectIdentifier *SrcObjId);
88 
89 typedef int (WINAPI * pWSAStartup) (WORD wVersionRequested,LPWSADATA lpWSAData);
90 
91 typedef UCHAR (WINAPI * pNetbios) (PNCB pncb);
92 
93 #endif
94 /*!
95     retrieve the 6-byte address of the network card; returns true on success
96 */
UT_getEthernetAddress(UT_EthernetAddress & A)97 bool UT_getEthernetAddress(UT_EthernetAddress &A)
98 {
99 #ifdef NO_MAC_ADDRESS
100 	// the following code by James Marsh <James.Marsh@sandtechnology.com>
101 	// was found at http://tangentsoft.net/wskfaq/examples/getmac-snmp.html
102 	// I adjusted it, so all the libs are dynamically loaded and unloaded
103 
104 	HINSTANCE m_hWSInst = NULL;
105 	m_hWSInst = LoadLibraryW(L"ws2_32.dll");
106 	pWSAStartup m_WSAStartup = NULL;
107 
108 	if(m_hWSInst < (HINSTANCE) HINSTANCE_ERROR)
109 	{
110 		UT_DEBUGMSG(("UT_getEthernetAddress: could not load ws2_32.dll\n"));
111 		m_hWSInst = NULL;
112 		goto  try_netbios;
113 	}
114 	else
115 	{
116 		m_WSAStartup = (pWSAStartup)   GetProcAddress(m_hWSInst, "WSAStartup");
117 		if(!m_WSAStartup)
118 		{
119 			UT_DEBUGMSG(("UT_getEthernetAddress: no WSAStartup\n"));
120 			FreeLibrary(m_hWSInst);
121 		}
122 	}
123 
124 	{
125 
126 		WSADATA WinsockData;
127 		if(m_WSAStartup(MAKEWORD(2, 0), &WinsockData) != 0)
128 		{
129 			UT_DEBUGMSG(("UT_getEthernetAddress: need Winsock 2.x!\n"));
130 			FreeLibrary(m_hWSInst);
131 			goto  try_netbios;
132 		}
133 
134 		HINSTANCE            m_hSNMPInst = NULL;
135 		pSnmpUtilVarBindFree m_SnmpUtilVarBindFree = NULL;
136 		pSnmpUtilOidNCmp     m_SnmpUtilOidNCmp = NULL;
137 		pSnmpUtilOidCpy      m_SnmpUtilOidCpy = NULL;
138 
139 
140 		HINSTANCE            m_hInst = NULL;
141 		pSnmpExtensionInit   m_Init = NULL;
142 		pSnmpExtensionQuery  m_Query = NULL;
143 		HANDLE               PollForTrapEvent;
144 		AsnObjectIdentifier  SupportedView;
145 
146 		UINT OID_ifEntryType[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 3};
147 		UINT OID_ifEntryNum[] = {1, 3, 6, 1, 2, 1, 2, 1};
148 		UINT OID_ipMACEntAddr[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 6};
149 
150 		AsnObjectIdentifier MIB_ifMACEntAddr = {sizeof(OID_ipMACEntAddr)/sizeof(UINT),
151 												OID_ipMACEntAddr};
152 
153 		AsnObjectIdentifier MIB_ifEntryType = {sizeof(OID_ifEntryType)/sizeof(UINT),
154 											   OID_ifEntryType};
155 
156 		AsnObjectIdentifier MIB_ifEntryNum = {sizeof(OID_ifEntryNum)/sizeof(UINT),
157 											  OID_ifEntryNum};
158 
159 		RFC1157VarBindList  varBindList;
160 		RFC1157VarBind      varBind[2];
161 		AsnInteger          errorStatus;
162 		AsnInteger          errorIndex;
163 		AsnObjectIdentifier MIB_NULL = {0,0};
164 
165 		int ret;
166 		int dtmp;
167 		int j = 0;
168 		bool bFound = false;
169 
170 		/* Load the SNMP dll and get the addresses of the functions
171 		   necessary */
172 		m_hSNMPInst = LoadLibraryW(L"snmpapi.dll");
173 		if(m_hSNMPInst < (HINSTANCE) HINSTANCE_ERROR)
174 		{
175 			UT_DEBUGMSG(("UT_getEthernetAddress: could not load snmpapi.dll\n"));
176 			m_hSNMPInst = NULL;
177 			goto  try_netbios;
178 		}
179 
180 		m_SnmpUtilVarBindFree = (pSnmpUtilVarBindFree) GetProcAddress(m_hSNMPInst,
181 																	  "SnmpUtilVarBindFree");
182 
183 		m_SnmpUtilOidNCmp = (pSnmpUtilOidNCmp) GetProcAddress(m_hSNMPInst,
184 																	  "SnmpUtilOidNCmp");
185 
186 		m_SnmpUtilOidCpy = (pSnmpUtilOidCpy) GetProcAddress(m_hSNMPInst,
187 																	  "SnmpUtilOidCpy");
188 
189 
190 		if(!m_SnmpUtilVarBindFree || !m_SnmpUtilOidNCmp || !m_SnmpUtilOidCpy)
191 		{
192 			UT_DEBUGMSG(("UT_getEthernetAddress (win32): could not load SNMP functions\n"));
193 			FreeLibrary(m_hSNMPInst);
194 			goto try_netbios;
195 		}
196 
197 
198 		// load the SNMP extension library
199 		m_hInst = LoadLibraryW(L"inetmib1.dll");
200 
201 		if(m_hInst < (HINSTANCE) HINSTANCE_ERROR)
202 		{
203 			UT_DEBUGMSG(("UT_getEthernetAddress: could not load inetmib1.dll\n"));
204 			m_hInst = NULL;
205 			FreeLibrary(m_hSNMPInst);
206 			goto  try_netbios;
207 		}
208 
209 		m_Init =   (pSnmpExtensionInit)   GetProcAddress(m_hInst, "SnmpExtensionInit");
210 		m_Query =  (pSnmpExtensionQuery)  GetProcAddress(m_hInst, "SnmpExtensionQuery");
211 
212 		if(!m_Init || !m_Query)
213 		{
214 			UT_DEBUGMSG(("UT_getEthernetAddress (win32): could not load SNMP ext functions\n"));
215 			FreeLibrary(m_hInst);
216 			FreeLibrary(m_hSNMPInst);
217 			goto try_netbios;
218 		}
219 
220 		m_Init(GetTickCount(), &PollForTrapEvent, &SupportedView);
221 
222 		/* Initialize the variable list to be retrieved by m_Query */
223 		varBindList.list = varBind;
224 		varBind[0].name  = MIB_NULL;
225 		varBind[1].name  = MIB_NULL;
226 
227 		/* Copy in the OID to find the number of entries in the
228 		   Inteface table */
229 		varBindList.len = 1;        /* Only retrieving one item */
230 		m_SnmpUtilOidCpy(&varBind[0].name, &MIB_ifEntryNum);
231 
232 		ret = m_Query(ASN_RFC1157_GETNEXTREQUEST, &varBindList, &errorStatus, &errorIndex);
233 
234 		UT_DEBUGMSG(("UT_getEthernetAddress: adapters in this system : %i\n",
235 					 varBind[0].value.asnValue.number));
236 
237 		varBindList.len = 2;
238 
239 		/* Copy in the OID of ifType, the type of interface */
240 		m_SnmpUtilOidCpy(&varBind[0].name, &MIB_ifEntryType);
241 
242 		/* Copy in the OID of ifPhysAddress, the address */
243 		m_SnmpUtilOidCpy(&varBind[1].name, &MIB_ifMACEntAddr);
244 
245 		do {
246 
247 			/* Submit the query.  Responses will be loaded into varBindList.
248 			   We can expect this call to succeed a # of times corresponding
249 			   to the # of adapters reported to be in the system */
250 			ret = m_Query(ASN_RFC1157_GETNEXTREQUEST, &varBindList, &errorStatus, &errorIndex);
251 
252 			if(!ret)
253 			{
254 				ret = 1;
255 			}
256 			else
257 			{
258 				/* Confirm that the proper type has been returned */
259 				ret = m_SnmpUtilOidNCmp(&varBind[0].name,
260 										&MIB_ifEntryType,
261 										MIB_ifEntryType.idLength);
262 			}
263 
264 			if (!ret)
265 			{
266 				j++;
267 				dtmp = varBind[0].value.asnValue.number;
268 				UT_DEBUGMSG(("UT_getEthernetAddress (win32): Interface #%i type : %i\n"
269 							 , j, dtmp));
270 
271 				/* Type 6 describes ethernet interfaces */
272 				if(dtmp == 6)
273 				{
274 					/* Confirm that we have an address here */
275 					ret = m_SnmpUtilOidNCmp(&varBind[1].name,
276 											&MIB_ifMACEntAddr,
277 											MIB_ifMACEntAddr.idLength);
278 
279 					if((!ret) && (varBind[1].value.asnValue.address.stream != NULL))
280 					{
281 						if(   (varBind[1].value.asnValue.address.stream[0] == 0x44)
282 						   && (varBind[1].value.asnValue.address.stream[1] == 0x45)
283 						   && (varBind[1].value.asnValue.address.stream[2] == 0x53)
284 						   && (varBind[1].value.asnValue.address.stream[3] == 0x54)
285 						   && (varBind[1].value.asnValue.address.stream[4] == 0x00))
286 						{
287 							/* Ignore all dial-up networking adapters */
288 							UT_DEBUGMSG(("UT_getEthernetAddress: #%i is a DUN adapter\n", j));
289 							continue;
290 						}
291 						if(   (varBind[1].value.asnValue.address.stream[0] == 0x00)
292 						   && (varBind[1].value.asnValue.address.stream[1] == 0x00)
293 						   && (varBind[1].value.asnValue.address.stream[2] == 0x00)
294 						   && (varBind[1].value.asnValue.address.stream[3] == 0x00)
295 						   && (varBind[1].value.asnValue.address.stream[4] == 0x00)
296 						   && (varBind[1].value.asnValue.address.stream[5] == 0x00))
297 						{
298 
299 							/* Ignore NULL addresses returned by other network
300 							   interfaces */
301 							UT_DEBUGMSG(("UT_getEthernetAddress (win32): Interface #%i is "
302 										 "a NULL address\n", j));
303 							continue;
304 						}
305 
306 						for(UT_uint32 k = 0; k < 6; ++k)
307 							A[k] = varBind[1].value.asnValue.address.stream[k];
308 
309 						UT_DEBUGMSG(("UT_getEthernetAddress : MAC Address of interface #%i: "
310 									 "%02x.%02x.%02x.%02x.%02x.%02x\n",
311 									 j,A[0],A[1],A[2],A[3],A[4],A[5]));
312 
313 						// we only need the first address we find ...
314 						bFound = true;
315 						break;
316 					} // if ((!ret) && (varBind[1].
317 				} // if (dtmp == 6)
318 			} //if (!ret) # 2
319 		}
320 		while (!ret);         /* Stop only on an error.  An error will occur
321 								 when we go exhaust the list of interfaces to
322 								 be examined */
323 
324 		/* Free the bindings */
325 		m_SnmpUtilVarBindFree(&varBind[0]);
326 		m_SnmpUtilVarBindFree(&varBind[1]);
327 
328 		FreeLibrary(m_hInst);
329 		FreeLibrary(m_hSNMPInst);
330 		FreeLibrary(m_hWSInst);
331 
332 		if(bFound)
333 			return true;
334 	}
335 
336  try_netbios:
337 	// this is the method described in MS win32 docs; it has one
338 	// fundamental shortcoming: not everyone uses netbios, so it is
339 	// here as a fall back in case the previous method does not work
340 	// I have adjusted the MS code so as to load and unload the dlls
341 	// dynamically
342 	{
343 		UT_DEBUGMSG(("UT_getEthernetAddress: unable to use SNMP\n"));
344 
345 		HINSTANCE m_hInst;
346 
347 		m_hInst = LoadLibraryW(L"netapi32.dll");
348 		if(m_hInst < (HINSTANCE) HINSTANCE_ERROR)
349 		{
350 			UT_DEBUGMSG(("UT_getEthernetAddress: could not load netapi32.dll\n"));
351 			return false;
352 		}
353 
354 		pNetbios m_Netbios = NULL;
355 		m_Netbios = (pNetbios) GetProcAddress(m_hInst, "Netbios");
356 
357 		if(!m_Netbios)
358 		{
359 			UT_DEBUGMSG(("UT_getEthernetAddress: could load netbios functions\n"));
360 			FreeLibrary(m_hInst);
361 			return false;
362 		}
363 
364 		NCB Ncb;
365 		UT_uint32 iRet;
366 		bool bRet = true;
367 
368 		memset(&Ncb, 0, sizeof(Ncb));
369 		Ncb.ncb_command = NCBRESET;
370 		Ncb.ncb_lana_num = 0;
371 
372 		iRet = m_Netbios(&Ncb);
373 		bRet = (NRC_GOODRET	== iRet);
374 
375 		if(!bRet)
376 		{
377 			UT_DEBUGMSG(("UT_getEthernetAddress: unable to use NETBIOS either\n"));
378 			FreeLibrary(m_hInst);
379 			return false;
380 		}
381 
382 		memset(&Ncb, 0, sizeof (Ncb));
383 		Ncb.ncb_command = NCBASTAT;
384 		Ncb.ncb_lana_num = 0;
385 
386 		char namebuf[] = "*               ";
387 		strcpy((char *)Ncb.ncb_callname, namebuf);
388 
389 		ASTAT Adapter;
390 		Ncb.ncb_buffer = (unsigned char *) &Adapter;
391 		Ncb.ncb_length = sizeof(Adapter);
392 
393 		iRet = m_Netbios(&Ncb);
394 		bRet &= (NRC_GOODRET	== iRet);
395 
396 		if(!bRet)
397 		{
398 			UT_DEBUGMSG(("UT_getEthernetAddress: unable to use NETBIOS2 either\n"));
399 			FreeLibrary(m_hInst);
400 			return false;
401 		}
402 
403 		for(UT_uint32 i = 0; i < 6; ++i)
404 			A[i] = Adapter.adapt.adapter_address[i];
405 
406 		UT_DEBUGMSG(("MAC Address is %02x-%02x-%02x-%02x-%02x-%02x\n",
407 					 A[0],A[1],A[2],A[3],A[4],A[5]));
408 
409 		FreeLibrary(m_hInst);
410 		return true;
411 	}
412 #else
413 	UT_return_val_if_fail(0, false);
414 #endif
415 }
416 
417 /*!
418     Class that implements an assert dialogue; this is a private class, we only access it
419     through UT_Win32ThrowAssert() function
420 */
421 class ABI_EXPORT UT_Win32AssertDlg
422 {
423 	friend int ABI_EXPORT UT_Win32ThrowAssert(const char *, const char *, int, int);
424 
425   private:
UT_Win32AssertDlg(const char * pCond,const char * pFile,int iLine,int iCount)426 	UT_Win32AssertDlg(const char * pCond, const char * pFile, int iLine, int iCount)
427 		: m_iLine(iLine), m_pCond(pCond), m_pFile(pFile), m_iCount(iCount), m_myHWND(NULL), m_bTimersPaused(false){};
~UT_Win32AssertDlg()428 	~UT_Win32AssertDlg(){};
429 
430 	static BOOL CALLBACK  s_dlgProc(HWND,UINT,WPARAM,LPARAM);
431 
432 	BOOL		  _onInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam);
433 	BOOL		  _onCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
434 
435 	enum answer {AN_Debug, AN_Ignore, AN_IgnoreAll, AN_Abort};
436 
437 	answer runModal();
438 
439 	static BOOL CALLBACK s_DisableWindows(HWND hwnd,	LPARAM lParam);
440 	void enableWindows();
441 
442 	int  m_iLine;
443 	const char * m_pCond;
444 	const char * m_pFile;
445 	int  m_iCount;
446 
447 	answer m_answer;
448 
449 	HWND m_myHWND;
450 	UT_GenericVector<HWND> m_vecDisabledWnds;
451 	bool m_bTimersPaused;
452 };
453 
454 /*!
455     This function wraps arround the Assert dialog class and handles the returned
456     responses; it will abort application if the user chose Abort.
457 
458     \return : 0 -- give control to debugger
459               > 0  ignore this time
460               < 0  ignore always
461 */
UT_Win32ThrowAssert(const char * pCond,const char * pFile,int iLine,int iCount)462 int ABI_EXPORT UT_Win32ThrowAssert(const char * pCond, const char * pFile, int iLine, int iCount)
463 {
464 	UT_Win32AssertDlg dlg(pCond, pFile, iLine, iCount);
465 	UT_Win32AssertDlg::answer a = dlg.runModal();
466 
467 	switch(a)
468 	{
469 		case UT_Win32AssertDlg::AN_Debug:
470 			return 0;
471 
472 		case UT_Win32AssertDlg::AN_Ignore:
473 			return 1;
474 
475 		case UT_Win32AssertDlg::AN_IgnoreAll:
476 			return -1;
477 
478 		case UT_Win32AssertDlg::AN_Abort:
479 			exit(0);
480 			return 1;
481 	}
482 
483 	return 1;
484 }
485 
s_dlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)486 BOOL CALLBACK UT_Win32AssertDlg::s_dlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
487 {
488 	// This is a static function.
489 
490 	UT_Win32AssertDlg * pThis;
491 
492 
493 	switch (msg){
494 	case WM_INITDIALOG:
495 		pThis = (UT_Win32AssertDlg *)lParam;
496 		SetWindowLongPtrW(hWnd,DWLP_USER,lParam);
497 		return pThis->_onInitDialog(hWnd,wParam,lParam);
498 
499 	case WM_COMMAND:
500 		pThis = (UT_Win32AssertDlg *)GetWindowLongPtrW(hWnd,DWLP_USER);
501 		return pThis->_onCommand(hWnd,wParam,lParam);
502 
503 	default:
504 		return 0;
505 	}
506 }
507 
runModal()508 UT_Win32AssertDlg::answer UT_Win32AssertDlg::runModal()
509 {
510 	LPSTR lpTemplate = MAKEINTRESOURCEA(UT_RID_DIALOG_ASSERT);
511 
512 	UT_DebugOnly<int> result = DialogBoxParamA(GetModuleHandleA(NULL),
513 								lpTemplate,
514 								NULL,
515 								(DLGPROC)s_dlgProc,(LPARAM)this);
516 
517 	UT_ASSERT_HARMLESS((result != -1));
518 
519 	return m_answer;
520 }
521 
_onCommand(HWND hWnd,WPARAM wParam,LPARAM)522 BOOL UT_Win32AssertDlg::_onCommand(HWND hWnd, WPARAM wParam, LPARAM /*lParam*/)
523 {
524 	WORD wId = LOWORD(wParam);
525 
526 	switch (wId)
527 	{
528 		case UT_RID_DIALOG_ASSERT_DEBUG:
529 			m_answer = AN_Debug;
530 			break;
531 
532 		case UT_RID_DIALOG_ASSERT_ABORT:
533 			m_answer = AN_Abort;
534 			break;
535 
536 		case UT_RID_DIALOG_ASSERT_IGNORE:
537 			m_answer = AN_Ignore;
538 			break;
539 
540 		case UT_RID_DIALOG_ASSERT_IGNOREALLWAYS:
541 			m_answer = AN_IgnoreAll;
542 			break;
543 
544 		default:
545 			return 0;
546 	}
547 
548 	enableWindows();
549 	UT_Win32Timer::pauseAllTimers(m_bTimersPaused);
550 	EndDialog(hWnd,0);
551 	return 1;
552 
553 }
554 
s_DisableWindows(HWND hwnd,LPARAM lParam)555 BOOL CALLBACK UT_Win32AssertDlg::s_DisableWindows(HWND hwnd,	LPARAM lParam)
556 {
557 	UT_Win32AssertDlg * pThis = (UT_Win32AssertDlg*)lParam;
558 
559 	if(pThis && (pThis->m_myHWND != hwnd) && IsWindowEnabled(hwnd))
560 	{
561 		pThis->m_vecDisabledWnds.addItem(hwnd);
562 		EnableWindow(hwnd, FALSE);
563 	}
564 
565 	// give me another one
566 	return TRUE;
567 }
568 
enableWindows()569 void UT_Win32AssertDlg::enableWindows()
570 {
571 	for(UT_sint32 i = 0; i < m_vecDisabledWnds.getItemCount(); i++)
572 	{
573 		EnableWindow(m_vecDisabledWnds.getNthItem(i), TRUE);
574 	}
575 
576 	m_vecDisabledWnds.clear();
577 }
578 
_onInitDialog(HWND hWnd,WPARAM,LPARAM lParam)579 BOOL UT_Win32AssertDlg::_onInitDialog(HWND hWnd, WPARAM /*wParam*/, LPARAM lParam)
580 {
581 	// pause all timers
582 	m_bTimersPaused = UT_Win32Timer::timersPaused();
583 	UT_Win32Timer::pauseAllTimers(true);
584 
585 	// We need to make this dlg 'Task Modal' (equivalent to MB_TASKMODAL of the
586 	// MessageBox() function), otherwise mutliple assert boxes can potentially be created
587 	// in response to things like mouse movement. The idea how to do this came from the
588 	// WINE mailing list (http://www.winehq.com/hypermail/wine-devel/2004/11/0320.html)
589 	// Basically, we disable all windows that belong to our thread, and remember which
590 	// windows we did disable, so we can enable them before the dlg box closes.
591 	m_myHWND = hWnd;
592 	EnumThreadWindows(GetCurrentThreadId(),	s_DisableWindows, lParam);
593 
594 	// set initial state
595 	SetDlgItemTextA(hWnd,UT_RID_DIALOG_ASSERT_FILE,m_pFile);
596 	SetDlgItemTextA(hWnd,UT_RID_DIALOG_ASSERT_CONDITION,m_pCond);
597 
598 	char buff[20];
599 	_snprintf(buff, 19, "%d",m_iLine);
600 	SetDlgItemTextA(hWnd,UT_RID_DIALOG_ASSERT_LINE,buff);
601 
602 	_snprintf(buff, 19, "%d",m_iCount);
603 	SetDlgItemTextA(hWnd,UT_RID_DIALOG_ASSERT_COUNT,buff);
604 
605 	return 1;				// 1 == we did not call SetFocus()
606 }
607