modified dll/win32/kernel32/debug/output.c
authorKJK::Hyperion <hackbunny@reactos.org>
Sat, 17 Jan 2009 17:40:42 +0000 (17:40 +0000)
committerKJK::Hyperion <hackbunny@reactos.org>
Sat, 17 Jan 2009 17:40:42 +0000 (17:40 +0000)
   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

svn path=/trunk/; revision=38828

reactos/dll/win32/kernel32/debug/output.c

index 79d16e2..13e4115 100644 (file)
@@ -4,7 +4,7 @@
  * PROJECT:         ReactOS system libraries
  * FILE:            lib/kernel32/debug/debugger.c
  * PURPOSE:         OutputDebugString()
- * PROGRAMMER:      KJK::Hyperion <noog@libero.it>
+ * PROGRAMMER:      KJK::Hyperion <hackbunny@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 @@ K32CreateDBMonMutex(void)
         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 @@ K32CreateDBMonMutex(void)
                                            &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 @@ K32CreateDBMonMutex(void)
                                            &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 @@ K32CreateDBMonMutex(void)
                                            &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 @@ K32CreateDBMonMutex(void)
     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 @@ K32CreateDBMonMutex(void)
                                       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 @@ K32CreateDBMonMutex(void)
                                       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 @@ K32CreateDBMonMutex(void)
                                       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 @@ K32CreateDBMonMutex(void)
                                             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
 
+l_Cleanup:
     /* 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 @@ VOID
 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 @@ OutputDebugStringW(LPCWSTR _OutputString)
 
     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);
+       }
 }