Author: hyperion
Date: Sat Jan 17 11:40:42 2009
New Revision: 38828
URL:
http://svn.reactos.org/svn/reactos?rev=38828&view=rev
Log:
modified dll/win32/kernel32/debug/output.c
KJK::Hyperion vs KJK::Hyperion: finishing the job I started in 2003
"please uncomment when GCC supports SEH": it kind of does now, but it's
totally unnecessary in K32CreateDBMonMutex
"FIXME: this will be pointless until GCC does SEH": no longer pointless, I
guess. 6 years after the fact, OutputDebugStringA finally sends the string to the
user-mode debugger. Now if only we could test it...
Use DBG_PRINTEXCEPTION_C symbolic constant instead of hardcoding its value
Some [FORMATTING]
Make K32CreateDBMonMutex, for symbol table hygiene
My e-mail address changed
Modified:
trunk/reactos/dll/win32/kernel32/debug/output.c
Modified: trunk/reactos/dll/win32/kernel32/debug/output.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/debug/o…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/debug/output.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/debug/output.c [iso-8859-1] Sat Jan 17 11:40:42 2009
@@ -4,7 +4,7 @@
* PROJECT: ReactOS system libraries
* FILE: lib/kernel32/debug/debugger.c
* PURPOSE: OutputDebugString()
- * PROGRAMMER: KJK::Hyperion <noog(a)libero.it>
+ * PROGRAMMER: KJK::Hyperion <hackbunny(a)reactos.com>
*/
/* INCLUDES ******************************************************************/
@@ -14,6 +14,7 @@
/* FUNCTIONS *****************************************************************/
/* Open or create the mutex used to communicate with the debug monitor */
+static
HANDLE
K32CreateDBMonMutex(void)
{
@@ -63,13 +64,7 @@
return NULL;
}
- /* if the mutex doesn't exist, create it */
-#if 0 /* please uncomment when GCC supports SEH */
- __try
- {
-#else
-#define __leave goto l_Cleanup
-#endif
+ /* if the mutex doesn't exist, create it */
/* first, set up the mutex security */
/* allocate the NT AUTHORITY\SYSTEM SID */
@@ -86,7 +81,7 @@
&psidSystem);
/* failure */
- if(!NT_SUCCESS(nErrCode)) __leave;
+ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
/* allocate the BUILTIN\Administrators SID */
nErrCode = RtlAllocateAndInitializeSid(&siaNTAuth,
@@ -102,7 +97,7 @@
&psidAdministrators);
/* failure */
- if(!NT_SUCCESS(nErrCode)) __leave;
+ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
/* allocate the Everyone SID */
nErrCode = RtlAllocateAndInitializeSid(&siaWorldAuth,
@@ -118,7 +113,7 @@
&psidEveryone);
/* failure */
- if(!NT_SUCCESS(nErrCode)) __leave;
+ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
/* allocate space for the SIDs too */
nDaclBufSize += RtlLengthSid(psidSystem);
@@ -129,13 +124,13 @@
pDaclBuf = GlobalAlloc(GMEM_FIXED, nDaclBufSize);
/* failure */
- if(pDaclBuf == NULL) __leave;
+ if(pDaclBuf == NULL) goto l_Cleanup;
/* create the DACL */
nErrCode = RtlCreateAcl(pDaclBuf, nDaclBufSize, ACL_REVISION);
/* failure */
- if(!NT_SUCCESS(nErrCode)) __leave;
+ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
/* grant the minimum required access to Everyone */
nErrCode = RtlAddAccessAllowedAce(pDaclBuf,
@@ -146,7 +141,7 @@
psidEveryone);
/* failure */
- if(!NT_SUCCESS(nErrCode)) __leave;
+ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
/* grant full access to BUILTIN\Administrators */
nErrCode = RtlAddAccessAllowedAce(pDaclBuf,
@@ -155,7 +150,7 @@
psidAdministrators);
/* failure */
- if(!NT_SUCCESS(nErrCode)) __leave;
+ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
/* grant full access to NT AUTHORITY\SYSTEM */
nErrCode = RtlAddAccessAllowedAce(pDaclBuf,
@@ -164,14 +159,14 @@
psidSystem);
/* failure */
- if(!NT_SUCCESS(nErrCode)) __leave;
+ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
/* create the security descriptor */
nErrCode = RtlCreateSecurityDescriptor(&sdMutexSecurity,
SECURITY_DESCRIPTOR_REVISION);
/* failure */
- if(!NT_SUCCESS(nErrCode)) __leave;
+ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
/* set the descriptor's DACL to the ACL we created */
nErrCode = RtlSetDaclSecurityDescriptor(&sdMutexSecurity,
@@ -180,28 +175,19 @@
FALSE);
/* failure */
- if(!NT_SUCCESS(nErrCode)) __leave;
+ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
/* create the mutex */
hMutex = CreateMutexW(&saMutexAttribs, FALSE, L"DBWinMutex");
-#if 0
- }
- __finally
- {
-#else
+
l_Cleanup:
-#endif
-
/* free the buffers */
if(pDaclBuf) GlobalFree(pDaclBuf);
if(psidEveryone) RtlFreeSid(psidEveryone);
if(psidAdministrators) RtlFreeSid(psidAdministrators);
if(psidSystem) RtlFreeSid(psidSystem);
-#if 0
- }
-#endif
-
- return hMutex;
+
+ return hMutex;
}
@@ -212,221 +198,195 @@
WINAPI
OutputDebugStringA(LPCSTR _OutputString)
{
-#if 0
-/* FIXME: this will be pointless until GCC does SEH */
- __try
- {
- ULONG_PTR a_nArgs[2];
-
- a_nArgs[0] = (ULONG_PTR)(strlen(_OutputString) + 1);
- a_nArgs[1] = (ULONG_PTR)_OutputString;
-
- /* send the string to the user-mode debugger */
- RaiseException(0x40010006, 0, 2, a_nArgs);
- }
- __except(EXCEPTION_EXECUTE_HANDLER)
- {
-#endif
-
- /* no user-mode debugger: try the systemwide debug message monitor, or the
- kernel debugger as a last resort */
-
- /* mutex used to synchronize invocations of OutputDebugString */
- static HANDLE s_hDBMonMutex = NULL;
- /* true if we already attempted to open/create the mutex */
- static BOOL s_bDBMonMutexTriedOpen = FALSE;
-
- /* local copy of the mutex handle */
- HANDLE hDBMonMutex = s_hDBMonMutex;
- /* handle to the Section of the shared buffer */
- HANDLE hDBMonBuffer = NULL;
-
- /* pointer to the mapped view of the shared buffer. It consist of the current
- process id followed by the message string */
- struct { DWORD ProcessId; CHAR Buffer[1]; } * pDBMonBuffer = NULL;
-
- /* event: signaled by the debug message monitor when OutputDebugString can write
- to the shared buffer */
- HANDLE hDBMonBufferReady = NULL;
-
- /* event: to be signaled by OutputDebugString when it's done writing to the
- shared buffer */
- HANDLE hDBMonDataReady = NULL;
-
- /* mutex not opened, and no previous attempts to open/create it */
- if(hDBMonMutex == NULL && !s_bDBMonMutexTriedOpen)
- {
- /* open/create the mutex */
- hDBMonMutex = K32CreateDBMonMutex();
- /* store the handle */
- s_hDBMonMutex = hDBMonMutex;
- }
-
-#if 0
- __try
- {
-#endif
-
- /* opening the mutex failed */
- if(hDBMonMutex == NULL)
- {
- /* remember next time */
- s_bDBMonMutexTriedOpen = TRUE;
- }
- /* opening the mutex succeeded */
- else
- {
- do
- {
- /* synchronize with other invocations of OutputDebugString */
- WaitForSingleObject(hDBMonMutex, INFINITE);
-
- /* buffer of the system-wide debug message monitor */
- hDBMonBuffer = OpenFileMappingW(SECTION_MAP_WRITE, FALSE,
L"DBWIN_BUFFER");
-
- /* couldn't open the buffer: send the string to the kernel debugger */
- if(hDBMonBuffer == NULL) break;
-
- /* map the buffer */
- pDBMonBuffer = MapViewOfFile(hDBMonBuffer,
- SECTION_MAP_READ | SECTION_MAP_WRITE,
- 0,
- 0,
- 0);
-
- /* couldn't map the buffer: send the string to the kernel debugger */
- if(pDBMonBuffer == NULL) break;
-
- /* open the event signaling that the buffer can be accessed */
- hDBMonBufferReady = OpenEventW(SYNCHRONIZE, FALSE,
L"DBWIN_BUFFER_READY");
-
- /* couldn't open the event: send the string to the kernel debugger */
- if(hDBMonBufferReady == NULL) break;
-
- /* open the event to be signaled when the buffer has been filled */
- hDBMonDataReady =
- OpenEventW(EVENT_MODIFY_STATE, FALSE, L"DBWIN_DATA_READY");
- }
- while(0);
-
- /* we couldn't connect to the system-wide debug message monitor: send the
- string to the kernel debugger */
- if(hDBMonDataReady == NULL) ReleaseMutex(hDBMonMutex);
- }
-
-#if 0
- __try
-#else
- do
-#endif
- {
- /* size of the current output block */
- SIZE_T nRoundLen;
-
- /* size of the remainder of the string */
- SIZE_T nOutputStringLen;
-
- /* output the whole string */
- nOutputStringLen = strlen(_OutputString);
-
- do
- {
- /* we're connected to the debug monitor:
- write the current block to the shared buffer */
- if(hDBMonDataReady)
- {
- /* wait a maximum of 10 seconds for the debug monitor
- to finish processing the shared buffer */
- if(WaitForSingleObject(hDBMonBufferReady, 10000) != WAIT_OBJECT_0)
- {
- /* timeout or failure: give up */
- break;
- }
-
- /* write the process id into the buffer */
- pDBMonBuffer->ProcessId = GetCurrentProcessId();
-
- /* write only as many bytes as they fit in the buffer */
- if(nOutputStringLen > (PAGE_SIZE - sizeof(DWORD) - 1))
- nRoundLen = PAGE_SIZE - sizeof(DWORD) - 1;
- else
- nRoundLen = nOutputStringLen;
-
- /* copy the current block into the buffer */
- memcpy(pDBMonBuffer->Buffer, _OutputString, nRoundLen);
-
- /* null-terminate the current block */
- pDBMonBuffer->Buffer[nRoundLen] = 0;
-
- /* signal that the data contains meaningful data and can be read */
- SetEvent(hDBMonDataReady);
- }
- /* else, send the current block to the kernel debugger */
- else
- {
- /* output in blocks of 512 characters */
- CHAR a_cBuffer[512];
-
- /* write a maximum of 511 bytes */
- if(nOutputStringLen > (sizeof(a_cBuffer) - 2))
- nRoundLen = sizeof(a_cBuffer) - 2;
- else
- nRoundLen = nOutputStringLen;
-
- /* copy the current block */
- memcpy(a_cBuffer, _OutputString, nRoundLen);
-
- /* null-terminate the current block */
- a_cBuffer[nRoundLen] = 0;
-
- /* send the current block to the kernel debugger */
- DbgPrint("%s", a_cBuffer);
- }
-
- /* move to the next block */
- _OutputString += nRoundLen;
- nOutputStringLen -= nRoundLen;
- }
- /* repeat until the string has been fully output */
- while (nOutputStringLen > 0);
-
- }
-#if 0
- /* ignore access violations and let other exceptions fall through */
- __except
- (
- (GetExceptionCode() == STATUS_ACCESS_VIOLATION) ?
- EXCEPTION_EXECUTE_HANDLER :
- EXCEPTION_CONTINUE_SEARCH
- )
- {
- /* string copied verbatim from Microsoft's kernel32.dll */
- DbgPrint("\nOutputDebugString faulted during output\n");
- }
-#else
- while(0);
-#endif
-
-#if 0
- }
- __finally
- {
-#endif
-
- /* close all the still open resources */
- if(hDBMonBufferReady) CloseHandle(hDBMonBufferReady);
- if(pDBMonBuffer) UnmapViewOfFile(pDBMonBuffer);
- if(hDBMonBuffer) CloseHandle(hDBMonBuffer);
- if(hDBMonDataReady) CloseHandle(hDBMonDataReady);
-
- /* leave the critical section */
- if(hDBMonDataReady != NULL)
- ReleaseMutex(hDBMonMutex);
-
-#if 0
- }
- }
-#endif
+ _SEH2_TRY
+ {
+ ULONG_PTR a_nArgs[2];
+
+ a_nArgs[0] = (ULONG_PTR)(strlen(_OutputString) + 1);
+ a_nArgs[1] = (ULONG_PTR)_OutputString;
+
+ /* send the string to the user-mode debugger */
+ RaiseException(DBG_PRINTEXCEPTION_C, 0, 2, a_nArgs);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* no user-mode debugger: try the systemwide debug message monitor, or the
+ kernel debugger as a last resort */
+
+ /* mutex used to synchronize invocations of OutputDebugString */
+ static HANDLE s_hDBMonMutex = NULL;
+ /* true if we already attempted to open/create the mutex */
+ static BOOL s_bDBMonMutexTriedOpen = FALSE;
+
+ /* local copy of the mutex handle */
+ HANDLE hDBMonMutex = s_hDBMonMutex;
+ /* handle to the Section of the shared buffer */
+ HANDLE hDBMonBuffer = NULL;
+
+ /* pointer to the mapped view of the shared buffer. It consist of the current
+ process id followed by the message string */
+ struct { DWORD ProcessId; CHAR Buffer[1]; } * pDBMonBuffer = NULL;
+
+ /* event: signaled by the debug message monitor when OutputDebugString can write
+ to the shared buffer */
+ HANDLE hDBMonBufferReady = NULL;
+
+ /* event: to be signaled by OutputDebugString when it's done writing to the
+ shared buffer */
+ HANDLE hDBMonDataReady = NULL;
+
+ /* mutex not opened, and no previous attempts to open/create it */
+ if(hDBMonMutex == NULL && !s_bDBMonMutexTriedOpen)
+ {
+ /* open/create the mutex */
+ hDBMonMutex = K32CreateDBMonMutex();
+ /* store the handle */
+ s_hDBMonMutex = hDBMonMutex;
+ }
+
+ _SEH2_TRY
+ {
+ /* opening the mutex failed */
+ if(hDBMonMutex == NULL)
+ {
+ /* remember next time */
+ s_bDBMonMutexTriedOpen = TRUE;
+ }
+ /* opening the mutex succeeded */
+ else
+ {
+ do
+ {
+ /* synchronize with other invocations of OutputDebugString */
+ WaitForSingleObject(hDBMonMutex, INFINITE);
+
+ /* buffer of the system-wide debug message monitor */
+ hDBMonBuffer = OpenFileMappingW(SECTION_MAP_WRITE, FALSE,
L"DBWIN_BUFFER");
+
+ /* couldn't open the buffer: send the string to the kernel debugger */
+ if(hDBMonBuffer == NULL) break;
+
+ /* map the buffer */
+ pDBMonBuffer = MapViewOfFile(hDBMonBuffer,
+ SECTION_MAP_READ | SECTION_MAP_WRITE,
+ 0,
+ 0,
+ 0);
+
+ /* couldn't map the buffer: send the string to the kernel debugger */
+ if(pDBMonBuffer == NULL) break;
+
+ /* open the event signaling that the buffer can be accessed */
+ hDBMonBufferReady = OpenEventW(SYNCHRONIZE, FALSE,
L"DBWIN_BUFFER_READY");
+
+ /* couldn't open the event: send the string to the kernel debugger */
+ if(hDBMonBufferReady == NULL) break;
+
+ /* open the event to be signaled when the buffer has been filled */
+ hDBMonDataReady = OpenEventW(EVENT_MODIFY_STATE, FALSE,
L"DBWIN_DATA_READY");
+ }
+ while(0);
+
+ /* we couldn't connect to the system-wide debug message monitor: send the
+ string to the kernel debugger */
+ if(hDBMonDataReady == NULL) ReleaseMutex(hDBMonMutex);
+ }
+
+ _SEH2_TRY
+ {
+ /* size of the current output block */
+ SIZE_T nRoundLen;
+
+ /* size of the remainder of the string */
+ SIZE_T nOutputStringLen;
+
+ /* output the whole string */
+ nOutputStringLen = strlen(_OutputString);
+
+ do
+ {
+ /* we're connected to the debug monitor:
+ write the current block to the shared buffer */
+ if(hDBMonDataReady)
+ {
+ /* wait a maximum of 10 seconds for the debug monitor
+ to finish processing the shared buffer */
+ if(WaitForSingleObject(hDBMonBufferReady, 10000) != WAIT_OBJECT_0)
+ {
+ /* timeout or failure: give up */
+ break;
+ }
+
+ /* write the process id into the buffer */
+ pDBMonBuffer->ProcessId = GetCurrentProcessId();
+
+ /* write only as many bytes as they fit in the buffer */
+ if(nOutputStringLen > (PAGE_SIZE - sizeof(DWORD) - 1))
+ nRoundLen = PAGE_SIZE - sizeof(DWORD) - 1;
+ else
+ nRoundLen = nOutputStringLen;
+
+ /* copy the current block into the buffer */
+ memcpy(pDBMonBuffer->Buffer, _OutputString, nRoundLen);
+
+ /* null-terminate the current block */
+ pDBMonBuffer->Buffer[nRoundLen] = 0;
+
+ /* signal that the data contains meaningful data and can be read */
+ SetEvent(hDBMonDataReady);
+ }
+ /* else, send the current block to the kernel debugger */
+ else
+ {
+ /* output in blocks of 512 characters */
+ CHAR a_cBuffer[512];
+
+ /* write a maximum of 511 bytes */
+ if(nOutputStringLen > (sizeof(a_cBuffer) - 2))
+ nRoundLen = sizeof(a_cBuffer) - 2;
+ else
+ nRoundLen = nOutputStringLen;
+
+ /* copy the current block */
+ memcpy(a_cBuffer, _OutputString, nRoundLen);
+
+ /* null-terminate the current block */
+ a_cBuffer[nRoundLen] = 0;
+
+ /* send the current block to the kernel debugger */
+ DbgPrint("%s", a_cBuffer);
+ }
+
+ /* move to the next block */
+ _OutputString += nRoundLen;
+ nOutputStringLen -= nRoundLen;
+ }
+ /* repeat until the string has been fully output */
+ while (nOutputStringLen > 0);
+ }
+ /* ignore access violations and let other exceptions fall through */
+ _SEH2_EXCEPT((_SEH2_GetExceptionCode() == STATUS_ACCESS_VIOLATION) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ /* string copied verbatim from Microsoft's kernel32.dll */
+ DbgPrint("\nOutputDebugString faulted during output\n");
+ }
+ _SEH2_END;
+ }
+ _SEH2_FINALLY
+ {
+ /* close all the still open resources */
+ if(hDBMonBufferReady) CloseHandle(hDBMonBufferReady);
+ if(pDBMonBuffer) UnmapViewOfFile(pDBMonBuffer);
+ if(hDBMonBuffer) CloseHandle(hDBMonBuffer);
+ if(hDBMonDataReady) CloseHandle(hDBMonDataReady);
+
+ /* leave the critical section */
+ if(hDBMonDataReady != NULL)
+ ReleaseMutex(hDBMonMutex);
+ }
+ _SEH2_END;
+ }
+ _SEH2_END;
}
@@ -447,15 +407,15 @@
if(!NT_SUCCESS(nErrCode))
{
- /* Microsoft's kernel32.dll always prints something, even in case the
conversion fails */
- OutputDebugStringA("");
- }
- else
- {
- /* output the converted string */
- OutputDebugStringA(strOut.Buffer);
-
- /* free the converted string */
- RtlFreeAnsiString(&strOut);
- }
+ /* Microsoft's kernel32.dll always prints something, even in case the conversion
fails */
+ OutputDebugStringA("");
+ }
+ else
+ {
+ /* output the converted string */
+ OutputDebugStringA(strOut.Buffer);
+
+ /* free the converted string */
+ RtlFreeAnsiString(&strOut);
+ }
}