ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

debugger.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Win32 Base API
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            dll/win32/kernel32/debug/debugger.c
00005  * PURPOSE:         Wrappers for the NT Debug Implementation
00006  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
00007  */
00008 
00009 /* INCLUDES *****************************************************************/
00010 
00011 #include <k32.h>
00012 #define NDEBUG
00013 #include <debug.h>
00014 
00015 typedef struct _DBGSS_THREAD_DATA
00016 {
00017     struct _DBGSS_THREAD_DATA *Next;
00018     HANDLE ThreadHandle;
00019     HANDLE ProcessHandle;
00020     DWORD ProcessId;
00021     DWORD ThreadId;
00022     BOOLEAN HandleMarked;
00023 } DBGSS_THREAD_DATA, *PDBGSS_THREAD_DATA;
00024 
00025 #define DbgSsSetThreadData(d) \
00026     NtCurrentTeb()->DbgSsReserved[0] = d
00027 
00028 #define DbgSsGetThreadData() \
00029     ((PDBGSS_THREAD_DATA)NtCurrentTeb()->DbgSsReserved[0])
00030 
00031 /* PRIVATE FUNCTIONS *********************************************************/
00032 
00033 static
00034 HANDLE
00035 K32CreateDBMonMutex(void)
00036 {
00037     static SID_IDENTIFIER_AUTHORITY siaNTAuth = {SECURITY_NT_AUTHORITY};
00038     static SID_IDENTIFIER_AUTHORITY siaWorldAuth = {SECURITY_WORLD_SID_AUTHORITY};
00039     HANDLE hMutex;
00040 
00041     /* SIDs to be used in the DACL */
00042     PSID psidSystem = NULL;
00043     PSID psidAdministrators = NULL;
00044     PSID psidEveryone = NULL;
00045 
00046     /* buffer for the DACL */
00047     PVOID pDaclBuf = NULL;
00048 
00049     /* minimum size of the DACL: an ACL descriptor and three ACCESS_ALLOWED_ACE
00050        headers. We'll add the size of SIDs when we'll know it
00051     */
00052     SIZE_T nDaclBufSize =
00053          sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE) -
00054                         sizeof(((ACCESS_ALLOWED_ACE*)0)->SidStart)) * 3;
00055 
00056     /* security descriptor of the mutex */
00057     SECURITY_DESCRIPTOR sdMutexSecurity;
00058 
00059     /* attributes of the mutex object we'll create */
00060     SECURITY_ATTRIBUTES saMutexAttribs = {sizeof(saMutexAttribs),
00061                                           &sdMutexSecurity,
00062                                           TRUE};
00063 
00064     NTSTATUS nErrCode;
00065 
00066     /* first, try to open the mutex */
00067     hMutex = OpenMutexW (SYNCHRONIZE | READ_CONTROL | MUTANT_QUERY_STATE,
00068                          TRUE,
00069                          L"DBWinMutex");
00070 
00071     if(hMutex != NULL)
00072     {
00073         /* success */
00074         return hMutex;
00075     }
00076     /* error other than the mutex not being found */
00077     else if(GetLastError() != ERROR_FILE_NOT_FOUND)
00078     {
00079         /* failure */
00080         return NULL;
00081     }
00082 
00083     /* if the mutex doesn't exist, create it */
00084 
00085     /* first, set up the mutex security */
00086     /* allocate the NT AUTHORITY\SYSTEM SID */
00087     nErrCode = RtlAllocateAndInitializeSid(&siaNTAuth,
00088                                            1,
00089                                            SECURITY_LOCAL_SYSTEM_RID,
00090                                            0,
00091                                            0,
00092                                            0,
00093                                            0,
00094                                            0,
00095                                            0,
00096                                            0,
00097                                            &psidSystem);
00098 
00099     /* failure */
00100     if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
00101 
00102     /* allocate the BUILTIN\Administrators SID */
00103     nErrCode = RtlAllocateAndInitializeSid(&siaNTAuth,
00104                                            2,
00105                                            SECURITY_BUILTIN_DOMAIN_RID,
00106                                            DOMAIN_ALIAS_RID_ADMINS,
00107                                            0,
00108                                            0,
00109                                            0,
00110                                            0,
00111                                            0,
00112                                            0,
00113                                            &psidAdministrators);
00114 
00115     /* failure */
00116     if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
00117 
00118     /* allocate the Everyone SID */
00119     nErrCode = RtlAllocateAndInitializeSid(&siaWorldAuth,
00120                                            1,
00121                                            0,
00122                                            0,
00123                                            0,
00124                                            0,
00125                                            0,
00126                                            0,
00127                                            0,
00128                                            0,
00129                                            &psidEveryone);
00130 
00131     /* failure */
00132     if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
00133 
00134     /* allocate space for the SIDs too */
00135     nDaclBufSize += RtlLengthSid(psidSystem);
00136     nDaclBufSize += RtlLengthSid(psidAdministrators);
00137     nDaclBufSize += RtlLengthSid(psidEveryone);
00138 
00139     /* allocate the buffer for the DACL */
00140     pDaclBuf = GlobalAlloc(GMEM_FIXED, nDaclBufSize);
00141 
00142     /* failure */
00143     if(pDaclBuf == NULL) goto l_Cleanup;
00144 
00145     /* create the DACL */
00146     nErrCode = RtlCreateAcl(pDaclBuf, nDaclBufSize, ACL_REVISION);
00147 
00148     /* failure */
00149     if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
00150 
00151     /* grant the minimum required access to Everyone */
00152     nErrCode = RtlAddAccessAllowedAce(pDaclBuf,
00153                                       ACL_REVISION,
00154                                       SYNCHRONIZE |
00155                                       READ_CONTROL |
00156                                       MUTANT_QUERY_STATE,
00157                                       psidEveryone);
00158 
00159     /* failure */
00160     if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
00161 
00162     /* grant full access to BUILTIN\Administrators */
00163     nErrCode = RtlAddAccessAllowedAce(pDaclBuf,
00164                                       ACL_REVISION,
00165                                       MUTANT_ALL_ACCESS,
00166                                       psidAdministrators);
00167 
00168     /* failure */
00169     if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
00170 
00171     /* grant full access to NT AUTHORITY\SYSTEM */
00172     nErrCode = RtlAddAccessAllowedAce(pDaclBuf,
00173                                       ACL_REVISION,
00174                                       MUTANT_ALL_ACCESS,
00175                                       psidSystem);
00176 
00177     /* failure */
00178     if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
00179 
00180     /* create the security descriptor */
00181     nErrCode = RtlCreateSecurityDescriptor(&sdMutexSecurity,
00182                                            SECURITY_DESCRIPTOR_REVISION);
00183 
00184     /* failure */
00185     if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
00186 
00187     /* set the descriptor's DACL to the ACL we created */
00188     nErrCode = RtlSetDaclSecurityDescriptor(&sdMutexSecurity,
00189                                             TRUE,
00190                                             pDaclBuf,
00191                                             FALSE);
00192 
00193     /* failure */
00194     if(!NT_SUCCESS(nErrCode)) goto l_Cleanup;
00195 
00196     /* create the mutex */
00197     hMutex = CreateMutexW(&saMutexAttribs, FALSE, L"DBWinMutex");
00198 
00199 l_Cleanup:
00200     /* free the buffers */
00201     if(pDaclBuf) GlobalFree(pDaclBuf);
00202     if(psidEveryone) RtlFreeSid(psidEveryone);
00203     if(psidAdministrators) RtlFreeSid(psidAdministrators);
00204     if(psidSystem) RtlFreeSid(psidSystem);
00205 
00206     return hMutex;
00207 }
00208 
00209 VOID
00210 WINAPI
00211 SaveThreadHandle(IN DWORD dwProcessId,
00212                  IN DWORD dwThreadId,
00213                  IN HANDLE hThread)
00214 {
00215     PDBGSS_THREAD_DATA ThreadData;
00216 
00217     /* Allocate a thread structure */
00218     ThreadData = RtlAllocateHeap(RtlGetProcessHeap(),
00219                                  0,
00220                                  sizeof(DBGSS_THREAD_DATA));
00221     if (!ThreadData) return;
00222 
00223     /* Fill it out */
00224     ThreadData->ThreadHandle = hThread;
00225     ThreadData->ProcessId = dwProcessId;
00226     ThreadData->ThreadId = dwThreadId;
00227     ThreadData->ProcessHandle = NULL;
00228     ThreadData->HandleMarked = FALSE;
00229 
00230     /* Link it */
00231     ThreadData->Next = DbgSsGetThreadData();
00232     DbgSsSetThreadData(ThreadData);
00233 }
00234 
00235 VOID
00236 WINAPI
00237 SaveProcessHandle(IN DWORD dwProcessId,
00238                   IN HANDLE hProcess)
00239 {
00240     PDBGSS_THREAD_DATA ThreadData;
00241 
00242     /* Allocate a thread structure */
00243     ThreadData = RtlAllocateHeap(RtlGetProcessHeap(),
00244                                  0,
00245                                  sizeof(DBGSS_THREAD_DATA));
00246     if (!ThreadData) return;
00247 
00248     /* Fill it out */
00249     ThreadData->ProcessHandle = hProcess;
00250     ThreadData->ProcessId = dwProcessId;
00251     ThreadData->ThreadId = 0;
00252     ThreadData->ThreadHandle = NULL;
00253     ThreadData->HandleMarked = FALSE;
00254 
00255     /* Link it */
00256     ThreadData->Next = DbgSsGetThreadData();
00257     DbgSsSetThreadData(ThreadData);
00258 }
00259 
00260 VOID
00261 WINAPI
00262 MarkThreadHandle(IN DWORD dwThreadId)
00263 {
00264     PDBGSS_THREAD_DATA ThreadData;
00265 
00266     /* Loop all thread data events */
00267     for (ThreadData = DbgSsGetThreadData(); ThreadData; ThreadData = ThreadData->Next)
00268     {
00269         /* Check if this one matches */
00270         if (ThreadData->ThreadId == dwThreadId)
00271         {
00272             /* Mark the structure and break out */
00273             ThreadData->HandleMarked = TRUE;
00274             break;
00275         }
00276     }
00277 }
00278 
00279 VOID
00280 WINAPI
00281 MarkProcessHandle(IN DWORD dwProcessId)
00282 {
00283     PDBGSS_THREAD_DATA ThreadData;
00284 
00285     /* Loop all thread data events */
00286     for (ThreadData = DbgSsGetThreadData(); ThreadData; ThreadData = ThreadData->Next)
00287     {
00288         /* Check if this one matches */
00289         if ((ThreadData->ProcessId == dwProcessId) && !(ThreadData->ThreadId))
00290         {
00291             /* Mark the structure and break out */
00292             ThreadData->HandleMarked = TRUE;
00293             break;
00294         }
00295     }
00296 }
00297 
00298 VOID
00299 WINAPI
00300 RemoveHandles(IN DWORD dwProcessId,
00301               IN DWORD dwThreadId)
00302 {
00303     PDBGSS_THREAD_DATA *ThreadData;
00304     PDBGSS_THREAD_DATA ThisData;
00305 
00306     /* Loop all thread data events */
00307     ThreadData = (PDBGSS_THREAD_DATA*)NtCurrentTeb()->DbgSsReserved;
00308     ThisData = *ThreadData;
00309     while(ThisData)
00310     {
00311         /* Check if this one matches */
00312         if ((ThisData->HandleMarked) &&
00313             ((ThisData->ProcessId == dwProcessId) || (ThisData->ThreadId == dwThreadId)))
00314         {
00315             /* Close open handles */
00316             if (ThisData->ThreadHandle) CloseHandle(ThisData->ThreadHandle);
00317             if (ThisData->ProcessHandle) CloseHandle(ThisData->ProcessHandle);
00318 
00319             /* Unlink the thread data */
00320             *ThreadData = ThisData->Next;
00321 
00322             /* Free it*/
00323             RtlFreeHeap(RtlGetProcessHeap(), 0, ThisData);
00324         }
00325         else
00326         {
00327             /* Move to the next one */
00328             ThreadData = &ThisData->Next;
00329         }
00330         ThisData = *ThreadData;
00331     }
00332 }
00333 
00334 VOID
00335 WINAPI
00336 CloseAllProcessHandles(IN DWORD dwProcessId)
00337 {
00338     PDBGSS_THREAD_DATA *ThreadData;
00339     PDBGSS_THREAD_DATA ThisData;
00340 
00341     /* Loop all thread data events */
00342     ThreadData = (PDBGSS_THREAD_DATA*)NtCurrentTeb()->DbgSsReserved;
00343     ThisData = *ThreadData;
00344     while(ThisData)
00345     {
00346         /* Check if this one matches */
00347         if (ThisData->ProcessId == dwProcessId)
00348         {
00349             /* Close open handles */
00350             if (ThisData->ThreadHandle) CloseHandle(ThisData->ThreadHandle);
00351             if (ThisData->ProcessHandle) CloseHandle(ThisData->ProcessHandle);
00352 
00353             /* Unlink the thread data */
00354             *ThreadData = ThisData->Next;
00355 
00356             /* Free it*/
00357             RtlFreeHeap(RtlGetProcessHeap(), 0, ThisData);
00358         }
00359         else
00360         {
00361             /* Move to the next one */
00362             ThreadData = &ThisData->Next;
00363         }
00364         ThisData = *ThreadData;
00365     }
00366 }
00367 
00368 HANDLE
00369 WINAPI
00370 ProcessIdToHandle(IN DWORD dwProcessId)
00371 {
00372     NTSTATUS Status;
00373     OBJECT_ATTRIBUTES ObjectAttributes;
00374     HANDLE Handle;
00375     CLIENT_ID ClientId;
00376 
00377     /* If we don't have a PID, look it up */
00378     if (dwProcessId == MAXDWORD) dwProcessId = (DWORD_PTR)CsrGetProcessId();
00379 
00380     /* Open a handle to the process */
00381     ClientId.UniqueThread = NULL;
00382     ClientId.UniqueProcess = UlongToHandle(dwProcessId);
00383     InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
00384     Status = NtOpenProcess(&Handle,
00385                            PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION |
00386                            PROCESS_VM_WRITE | PROCESS_VM_READ |
00387                            PROCESS_SUSPEND_RESUME | PROCESS_QUERY_INFORMATION,
00388                            &ObjectAttributes,
00389                            &ClientId);
00390     if (!NT_SUCCESS(Status))
00391     {
00392         /* Fail */
00393         BaseSetLastNTError(Status);
00394         return 0;
00395     }
00396 
00397     /* Return the handle */
00398     return Handle;
00399 }
00400 
00401 /* PUBLIC FUNCTIONS **********************************************************/
00402 
00403 /*
00404  * @implemented
00405  */
00406 BOOL
00407 WINAPI
00408 CheckRemoteDebuggerPresent(IN HANDLE hProcess,
00409                            OUT PBOOL pbDebuggerPresent)
00410 {
00411     HANDLE DebugPort;
00412     NTSTATUS Status;
00413 
00414     /* Make sure we have an output and process*/
00415     if (!(pbDebuggerPresent) || !(hProcess))
00416     {
00417         /* Fail */
00418         SetLastError(ERROR_INVALID_PARAMETER);
00419         return FALSE;
00420     }
00421 
00422     /* Check if the process has a debug object/port */
00423     Status = NtQueryInformationProcess(hProcess,
00424                                        ProcessDebugPort,
00425                                        (PVOID)&DebugPort,
00426                                        sizeof(HANDLE),
00427                                        NULL);
00428     if (NT_SUCCESS(Status))
00429     {
00430         /* Return the current state */
00431         *pbDebuggerPresent = DebugPort != NULL;
00432         return TRUE;
00433     }
00434 
00435     /* Otherwise, fail */
00436     BaseSetLastNTError(Status);
00437     return FALSE;
00438 }
00439 
00440 /*
00441  * @implemented
00442  */
00443 BOOL
00444 WINAPI
00445 ContinueDebugEvent(IN DWORD dwProcessId,
00446                    IN DWORD dwThreadId,
00447                    IN DWORD dwContinueStatus)
00448 {
00449     CLIENT_ID ClientId;
00450     NTSTATUS Status;
00451 
00452     /* Set the Client ID */
00453     ClientId.UniqueProcess = (HANDLE)dwProcessId;
00454     ClientId.UniqueThread = (HANDLE)dwThreadId;
00455 
00456     /* Continue debugging */
00457     Status = DbgUiContinue(&ClientId, dwContinueStatus);
00458     if (!NT_SUCCESS(Status))
00459     {
00460         /* Fail */
00461         BaseSetLastNTError(Status);
00462         return FALSE;
00463     }
00464 
00465     /* Remove the process/thread handles */
00466     RemoveHandles(dwProcessId, dwThreadId);
00467 
00468     /* Success */
00469     return TRUE;
00470 }
00471 
00472 /*
00473  * @implemented
00474  */
00475 BOOL
00476 WINAPI
00477 DebugActiveProcess(IN DWORD dwProcessId)
00478 {
00479     NTSTATUS Status, Status1;
00480     HANDLE Handle;
00481 
00482     /* Connect to the debugger */
00483     Status = DbgUiConnectToDbg();
00484     if (!NT_SUCCESS(Status))
00485     {
00486         BaseSetLastNTError(Status);
00487         return FALSE;
00488     }
00489 
00490     /* Get the process handle */
00491     Handle = ProcessIdToHandle(dwProcessId);
00492     if (!Handle) return FALSE;
00493 
00494     /* Now debug the process */
00495     Status = DbgUiDebugActiveProcess(Handle);
00496     
00497     /* Close the handle since we're done */
00498     Status1 = NtClose(Handle);
00499     ASSERT(NT_SUCCESS(Status1));
00500 
00501     /* Check if debugging worked */
00502     if (!NT_SUCCESS(Status))
00503     {
00504         /* Fail */
00505         BaseSetLastNTError(Status);
00506         return FALSE;
00507     }
00508 
00509     /* Success */
00510     return TRUE;
00511 }
00512 
00513 /*
00514  * @implemented
00515  */
00516 BOOL
00517 WINAPI
00518 DebugActiveProcessStop(IN DWORD dwProcessId)
00519 {
00520     NTSTATUS Status, Status1;
00521     HANDLE Handle;
00522 
00523     /* Get the process handle */
00524     Handle = ProcessIdToHandle(dwProcessId);
00525     if (!Handle) return FALSE;
00526 
00527     /* Close all the process handles */
00528     CloseAllProcessHandles(dwProcessId);
00529 
00530     /* Now stop debgging the process */
00531     Status = DbgUiStopDebugging(Handle);
00532     Status1 = NtClose(Handle);
00533     ASSERT(NT_SUCCESS(Status1));
00534 
00535     /* Check for failure */
00536     if (!NT_SUCCESS(Status))
00537     {
00538         /* Fail */
00539         SetLastError(ERROR_ACCESS_DENIED);
00540         return FALSE;
00541     }
00542 
00543     /* Success */
00544     return TRUE;
00545 }
00546 
00547 /*
00548  * @implemented
00549  */
00550 BOOL
00551 WINAPI
00552 DebugBreakProcess(IN HANDLE Process)
00553 {
00554     NTSTATUS Status;
00555 
00556     /* Send the breakin request */
00557     Status = DbgUiIssueRemoteBreakin(Process);
00558     if(!NT_SUCCESS(Status))
00559     {
00560         /* Failure */
00561         BaseSetLastNTError(Status);
00562         return FALSE;
00563     }
00564 
00565     /* Success */
00566     return TRUE;
00567 }
00568 
00569 /*
00570  * @implemented
00571  */
00572 BOOL
00573 WINAPI
00574 DebugSetProcessKillOnExit(IN BOOL KillOnExit)
00575 {
00576     HANDLE Handle;
00577     NTSTATUS Status;
00578     ULONG State;
00579 
00580     /* Get the debug object */
00581     Handle = DbgUiGetThreadDebugObject();
00582     if (!Handle)
00583     {
00584         /* Fail */
00585         BaseSetLastNTError(STATUS_INVALID_HANDLE);
00586         return FALSE;
00587     }
00588 
00589     /* Now set the kill-on-exit state */
00590     State = KillOnExit != 0;
00591     Status = NtSetInformationDebugObject(Handle,
00592                                          DebugObjectKillProcessOnExitInformation,
00593                                          &State,
00594                                          sizeof(State),
00595                                          NULL);
00596     if (!NT_SUCCESS(Status))
00597     {
00598         /* Fail */
00599         BaseSetLastNTError(Status);
00600         return FALSE;
00601     }
00602 
00603     /* Success */
00604     return TRUE;
00605 }
00606 
00607 /*
00608  * @implemented
00609  */
00610 BOOL
00611 WINAPI
00612 IsDebuggerPresent(VOID)
00613 {
00614     return (BOOL)NtCurrentPeb()->BeingDebugged;
00615 }
00616 
00617 /*
00618  * @implemented
00619  */
00620 BOOL
00621 WINAPI
00622 WaitForDebugEvent(IN LPDEBUG_EVENT lpDebugEvent,
00623                   IN DWORD dwMilliseconds)
00624 {
00625     LARGE_INTEGER WaitTime;
00626     PLARGE_INTEGER Timeout;
00627     DBGUI_WAIT_STATE_CHANGE WaitStateChange;
00628     NTSTATUS Status;
00629 
00630     /* Convert to NT Timeout */
00631     Timeout = BaseFormatTimeOut(&WaitTime, dwMilliseconds);
00632 
00633     /* Loop while we keep getting interrupted */
00634     do
00635     {
00636         /* Call the native API */
00637         Status = DbgUiWaitStateChange(&WaitStateChange, Timeout);
00638     } while ((Status == STATUS_ALERTED) || (Status == STATUS_USER_APC));
00639 
00640     /* Check if the wait failed */
00641     if (!(NT_SUCCESS(Status)) || (Status == DBG_UNABLE_TO_PROVIDE_HANDLE))
00642     {
00643         /* Set the error code and quit */
00644         BaseSetLastNTError(Status);
00645         return FALSE;
00646     }
00647 
00648     /* Check if we timed out */
00649     if (Status == STATUS_TIMEOUT)
00650     {
00651         /* Fail with a timeout error */
00652         SetLastError(ERROR_SEM_TIMEOUT);
00653         return FALSE;
00654     }
00655 
00656     /* Convert the structure */
00657     Status = DbgUiConvertStateChangeStructure(&WaitStateChange, lpDebugEvent);
00658     if (!NT_SUCCESS(Status))
00659     {
00660         /* Set the error code and quit */
00661         BaseSetLastNTError(Status);
00662         return FALSE;
00663     }
00664 
00665     /* Check what kind of event this was */
00666     switch (lpDebugEvent->dwDebugEventCode)
00667     {
00668         /* New thread was created */
00669         case CREATE_THREAD_DEBUG_EVENT:
00670 
00671             /* Setup the thread data */
00672             SaveThreadHandle(lpDebugEvent->dwProcessId,
00673                              lpDebugEvent->dwThreadId,
00674                              lpDebugEvent->u.CreateThread.hThread);
00675             break;
00676 
00677         /* New process was created */
00678         case CREATE_PROCESS_DEBUG_EVENT:
00679 
00680             /* Setup the process data */
00681             SaveProcessHandle(lpDebugEvent->dwProcessId,
00682                               lpDebugEvent->u.CreateProcessInfo.hProcess);
00683 
00684             /* Setup the thread data */
00685             SaveThreadHandle(lpDebugEvent->dwProcessId,
00686                              lpDebugEvent->dwThreadId,
00687                              lpDebugEvent->u.CreateProcessInfo.hThread);
00688             break;
00689 
00690         /* Process was exited */
00691         case EXIT_PROCESS_DEBUG_EVENT:
00692 
00693             /* Mark the thread data as such and fall through */
00694             MarkProcessHandle(lpDebugEvent->dwProcessId);
00695 
00696         /* Thread was exited */
00697         case EXIT_THREAD_DEBUG_EVENT:
00698 
00699             /* Mark the thread data */
00700             MarkThreadHandle(lpDebugEvent->dwThreadId);
00701             break;
00702     
00703         /* Nothing to do */
00704         case EXCEPTION_DEBUG_EVENT:
00705         case LOAD_DLL_DEBUG_EVENT:
00706         case UNLOAD_DLL_DEBUG_EVENT:
00707         case OUTPUT_DEBUG_STRING_EVENT:
00708         case RIP_EVENT:
00709             break;
00710 
00711         /* Fail anything else */
00712         default:
00713             return FALSE;
00714     }
00715 
00716     /* Return success */
00717     return TRUE;
00718 }
00719 
00720 /*
00721  * @implemented
00722  */
00723 VOID
00724 WINAPI
00725 OutputDebugStringA(IN LPCSTR _OutputString)
00726 {
00727     _SEH2_TRY
00728     {
00729         ULONG_PTR a_nArgs[2];
00730 
00731         a_nArgs[0] = (ULONG_PTR)(strlen(_OutputString) + 1);
00732         a_nArgs[1] = (ULONG_PTR)_OutputString;
00733 
00734         /* send the string to the user-mode debugger */
00735         RaiseException(DBG_PRINTEXCEPTION_C, 0, 2, a_nArgs);
00736     }
00737     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00738     {
00739         /* no user-mode debugger: try the systemwide debug message monitor, or the
00740            kernel debugger as a last resort */
00741 
00742         /* mutex used to synchronize invocations of OutputDebugString */
00743         static HANDLE s_hDBMonMutex = NULL;
00744         /* true if we already attempted to open/create the mutex */
00745         static BOOL s_bDBMonMutexTriedOpen = FALSE;
00746 
00747         /* local copy of the mutex handle */
00748         volatile HANDLE hDBMonMutex = s_hDBMonMutex;
00749         /* handle to the Section of the shared buffer */
00750         volatile HANDLE hDBMonBuffer = NULL;
00751 
00752         /* pointer to the mapped view of the shared buffer. It consist of the current
00753            process id followed by the message string */
00754         struct { DWORD ProcessId; CHAR Buffer[1]; } * pDBMonBuffer = NULL;
00755 
00756         /* event: signaled by the debug message monitor when OutputDebugString can write
00757            to the shared buffer */
00758         volatile HANDLE hDBMonBufferReady = NULL;
00759 
00760         /* event: to be signaled by OutputDebugString when it's done writing to the
00761            shared buffer */
00762         volatile HANDLE hDBMonDataReady = NULL;
00763 
00764         /* mutex not opened, and no previous attempts to open/create it */
00765         if(hDBMonMutex == NULL && !s_bDBMonMutexTriedOpen)
00766         {
00767             /* open/create the mutex */
00768             hDBMonMutex = K32CreateDBMonMutex();
00769             /* store the handle */
00770             s_hDBMonMutex = hDBMonMutex;
00771         }
00772 
00773         _SEH2_TRY
00774         {
00775             volatile PCHAR a_cBuffer = NULL;
00776 
00777             /* opening the mutex failed */
00778             if(hDBMonMutex == NULL)
00779             {
00780                 /* remember next time */
00781                 s_bDBMonMutexTriedOpen = TRUE;
00782             }
00783             /* opening the mutex succeeded */
00784             else
00785             {
00786                 do
00787                 {
00788                     /* synchronize with other invocations of OutputDebugString */
00789                     WaitForSingleObject(hDBMonMutex, INFINITE);
00790 
00791                     /* buffer of the system-wide debug message monitor */
00792                     hDBMonBuffer = OpenFileMappingW(SECTION_MAP_WRITE, FALSE, L"DBWIN_BUFFER");
00793 
00794                     /* couldn't open the buffer: send the string to the kernel debugger */
00795                     if(hDBMonBuffer == NULL) break;
00796 
00797                     /* map the buffer */
00798                     pDBMonBuffer = MapViewOfFile(hDBMonBuffer,
00799                                                  SECTION_MAP_READ | SECTION_MAP_WRITE,
00800                                                  0,
00801                                                  0,
00802                                                  0);
00803 
00804                     /* couldn't map the buffer: send the string to the kernel debugger */
00805                     if(pDBMonBuffer == NULL) break;
00806 
00807                     /* open the event signaling that the buffer can be accessed */
00808                     hDBMonBufferReady = OpenEventW(SYNCHRONIZE, FALSE, L"DBWIN_BUFFER_READY");
00809 
00810                     /* couldn't open the event: send the string to the kernel debugger */
00811                     if(hDBMonBufferReady == NULL) break;
00812 
00813                     /* open the event to be signaled when the buffer has been filled */
00814                     hDBMonDataReady = OpenEventW(EVENT_MODIFY_STATE, FALSE, L"DBWIN_DATA_READY");
00815                 }
00816                 while(0);
00817 
00818                 /* we couldn't connect to the system-wide debug message monitor: send the
00819                    string to the kernel debugger */
00820                 if(hDBMonDataReady == NULL) ReleaseMutex(hDBMonMutex);
00821             }
00822 
00823             _SEH2_TRY
00824             {
00825                 /* size of the current output block */
00826                 volatile SIZE_T nRoundLen;
00827 
00828                 /* size of the remainder of the string */
00829                 volatile SIZE_T nOutputStringLen;
00830 
00831                 /* output the whole string */
00832                 nOutputStringLen = strlen(_OutputString);
00833 
00834                 do
00835                 {
00836                     /* we're connected to the debug monitor:
00837                        write the current block to the shared buffer */
00838                     if(hDBMonDataReady)
00839                     {
00840                         /* wait a maximum of 10 seconds for the debug monitor
00841                            to finish processing the shared buffer */
00842                         if(WaitForSingleObject(hDBMonBufferReady, 10000) != WAIT_OBJECT_0)
00843                         {
00844                             /* timeout or failure: give up */
00845                             break;
00846                         }
00847 
00848                         /* write the process id into the buffer */
00849                         pDBMonBuffer->ProcessId = GetCurrentProcessId();
00850 
00851                         /* write only as many bytes as they fit in the buffer */
00852                         if(nOutputStringLen > (PAGE_SIZE - sizeof(DWORD) - 1))
00853                             nRoundLen = PAGE_SIZE - sizeof(DWORD) - 1;
00854                         else
00855                             nRoundLen = nOutputStringLen;
00856 
00857                         /* copy the current block into the buffer */
00858                         memcpy(pDBMonBuffer->Buffer, _OutputString, nRoundLen);
00859 
00860                         /* null-terminate the current block */
00861                         pDBMonBuffer->Buffer[nRoundLen] = 0;
00862 
00863                         /* signal that the data contains meaningful data and can be read */
00864                         SetEvent(hDBMonDataReady);
00865                     }
00866                     /* else, send the current block to the kernel debugger */
00867                     else
00868                     {
00869                         /* output in blocks of 512 characters */
00870                         a_cBuffer = (CHAR*)HeapAlloc(GetProcessHeap(), 0, 512);
00871 
00872                         if (!a_cBuffer)
00873                         {
00874                             DbgPrint("OutputDebugStringA: Failed\n");
00875                             break;
00876                         }
00877 
00878                         /* write a maximum of 511 bytes */
00879                         if(nOutputStringLen > 510)
00880                             nRoundLen = 510;
00881                         else
00882                             nRoundLen = nOutputStringLen;
00883 
00884                         /* copy the current block */
00885                         memcpy(a_cBuffer, _OutputString, nRoundLen);
00886 
00887                         /* null-terminate the current block */
00888                         a_cBuffer[nRoundLen] = 0;
00889 
00890                         /* send the current block to the kernel debugger */
00891                         DbgPrint("%s", a_cBuffer);
00892 
00893                         if (a_cBuffer)
00894                         {
00895                             HeapFree(GetProcessHeap(), 0, a_cBuffer);
00896                             a_cBuffer = NULL;
00897                         }
00898                     }
00899 
00900                     /* move to the next block */
00901                     _OutputString += nRoundLen;
00902                     nOutputStringLen -= nRoundLen;
00903                 }
00904                 /* repeat until the string has been fully output */
00905                 while (nOutputStringLen > 0);
00906             }
00907             /* ignore access violations and let other exceptions fall through */
00908             _SEH2_EXCEPT((_SEH2_GetExceptionCode() == STATUS_ACCESS_VIOLATION) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
00909             {
00910                 if (a_cBuffer)
00911                     HeapFree(GetProcessHeap(), 0, a_cBuffer);
00912 
00913                 /* string copied verbatim from Microsoft's kernel32.dll */
00914                 DbgPrint("\nOutputDebugString faulted during output\n");
00915             }
00916             _SEH2_END;
00917         }
00918         _SEH2_FINALLY
00919         {
00920             /* close all the still open resources */
00921             if(hDBMonBufferReady) CloseHandle(hDBMonBufferReady);
00922             if(pDBMonBuffer) UnmapViewOfFile(pDBMonBuffer);
00923             if(hDBMonBuffer) CloseHandle(hDBMonBuffer);
00924             if(hDBMonDataReady) CloseHandle(hDBMonDataReady);
00925 
00926             /* leave the critical section */
00927             if(hDBMonDataReady != NULL)
00928                 ReleaseMutex(hDBMonMutex);
00929         }
00930         _SEH2_END;
00931     }
00932     _SEH2_END;
00933 }
00934 
00935 /*
00936  * @implemented
00937  */
00938 VOID
00939 WINAPI
00940 OutputDebugStringW(IN LPCWSTR OutputString)
00941 {
00942     UNICODE_STRING UnicodeString;
00943     ANSI_STRING AnsiString;
00944     NTSTATUS Status;
00945 
00946     /* convert the string in ANSI */
00947     RtlInitUnicodeString(&UnicodeString, OutputString);
00948     Status = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, TRUE);
00949 
00950     /* OutputDebugStringW always prints something, even if conversion fails */
00951     if (!NT_SUCCESS(Status)) AnsiString.Buffer = "";
00952 
00953     /* Output the converted string */
00954     OutputDebugStringA(AnsiString.Buffer);
00955 
00956     /* free the converted string */
00957     if (NT_SUCCESS(Status)) RtlFreeAnsiString(&AnsiString);
00958 }
00959 
00960 /* EOF */

Generated on Sat May 26 2012 04:22:56 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.