Author: sginsberg Date: Sat Sep 6 08:57:34 2008 New Revision: 35983
URL: http://svn.reactos.org/svn/reactos?rev=35983&view=rev Log: - [FORMATTING] Clean up output.c. No code change.
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/ou... ============================================================================== --- trunk/reactos/dll/win32/kernel32/debug/output.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/debug/output.c [iso-8859-1] Sat Sep 6 08:57:34 2008 @@ -14,64 +14,54 @@ /* FUNCTIONS *****************************************************************/
/* Open or create the mutex used to communicate with the debug monitor */ -HANDLE K32CreateDBMonMutex(void) +HANDLE +K32CreateDBMonMutex(void) { - static SID_IDENTIFIER_AUTHORITY siaNTAuth = {SECURITY_NT_AUTHORITY}; - static SID_IDENTIFIER_AUTHORITY siaWorldAuth = {SECURITY_WORLD_SID_AUTHORITY}; - - HANDLE hMutex; - - /* SIDs to be used in the DACL */ - PSID psidSystem = NULL; - PSID psidAdministrators = NULL; - PSID psidEveryone = NULL; - - /* buffer for the DACL */ - PVOID pDaclBuf = NULL; - - /* - minimum size of the DACL: an ACL descriptor and three ACCESS_ALLOWED_ACE - headers. We'll add the size of SIDs when we'll know it - */ - SIZE_T nDaclBufSize = - sizeof(ACL) + - ( - sizeof(ACCESS_ALLOWED_ACE) - - sizeof(((ACCESS_ALLOWED_ACE*)0)->SidStart) - ) * 3; - - /* security descriptor of the mutex */ - SECURITY_DESCRIPTOR sdMutexSecurity; - - /* attributes of the mutex object we'll create */ - SECURITY_ATTRIBUTES saMutexAttribs = - { - sizeof(saMutexAttribs), - &sdMutexSecurity, - TRUE - }; - - NTSTATUS nErrCode; - - /* first, try to open the mutex */ - hMutex = OpenMutexW - ( - SYNCHRONIZE | READ_CONTROL | MUTANT_QUERY_STATE, - TRUE, - L"DBWinMutex" - ); - - if(hMutex != NULL) - { - /* success */ - return hMutex; - } - /* error other than the mutex not being found */ - else if(GetLastError() != ERROR_FILE_NOT_FOUND) - { - /* failure */ - return NULL; - } + static SID_IDENTIFIER_AUTHORITY siaNTAuth = {SECURITY_NT_AUTHORITY}; + static SID_IDENTIFIER_AUTHORITY siaWorldAuth = {SECURITY_WORLD_SID_AUTHORITY}; + HANDLE hMutex; + + /* SIDs to be used in the DACL */ + PSID psidSystem = NULL; + PSID psidAdministrators = NULL; + PSID psidEveryone = NULL; + + /* buffer for the DACL */ + PVOID pDaclBuf = NULL; + + /* minimum size of the DACL: an ACL descriptor and three ACCESS_ALLOWED_ACE + headers. We'll add the size of SIDs when we'll know it + */ + SIZE_T nDaclBufSize = + sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE) - + sizeof(((ACCESS_ALLOWED_ACE*)0)->SidStart)) * 3; + + /* security descriptor of the mutex */ + SECURITY_DESCRIPTOR sdMutexSecurity; + + /* attributes of the mutex object we'll create */ + SECURITY_ATTRIBUTES saMutexAttribs = {sizeof(saMutexAttribs), + &sdMutexSecurity, + TRUE}; + + NTSTATUS nErrCode; + + /* first, try to open the mutex */ + hMutex = OpenMutexW (SYNCHRONIZE | READ_CONTROL | MUTANT_QUERY_STATE, + TRUE, + L"DBWinMutex"); + + if(hMutex != NULL) + { + /* success */ + return hMutex; + } + /* error other than the mutex not being found */ + else if(GetLastError() != ERROR_FILE_NOT_FOUND) + { + /* failure */ + return NULL; + }
/* if the mutex doesn't exist, create it */ #if 0 /* please uncomment when GCC supports SEH */ @@ -80,141 +70,120 @@ #else #define __leave goto l_Cleanup #endif - /* first, set up the mutex security */ - /* allocate the NT AUTHORITY\SYSTEM SID */ - nErrCode = RtlAllocateAndInitializeSid - ( - &siaNTAuth, - 1, - SECURITY_LOCAL_SYSTEM_RID, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - &psidSystem - ); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) __leave; - - /* allocate the BUILTIN\Administrators SID */ - nErrCode = RtlAllocateAndInitializeSid - ( - &siaNTAuth, - 2, - SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, - 0, - 0, - 0, - 0, - 0, - 0, - &psidAdministrators - ); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) __leave; - - /* allocate the Everyone SID */ - nErrCode = RtlAllocateAndInitializeSid - ( - &siaWorldAuth, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - &psidEveryone - ); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) __leave; - - /* allocate space for the SIDs too */ - nDaclBufSize += RtlLengthSid(psidSystem); - nDaclBufSize += RtlLengthSid(psidAdministrators); - nDaclBufSize += RtlLengthSid(psidEveryone); - - /* allocate the buffer for the DACL */ - pDaclBuf = GlobalAlloc(GMEM_FIXED, nDaclBufSize); - - /* failure */ - if(pDaclBuf == NULL) __leave; - - /* create the DACL */ - nErrCode = RtlCreateAcl(pDaclBuf, nDaclBufSize, ACL_REVISION); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) __leave; - - /* grant the minimum required access to Everyone */ - nErrCode = RtlAddAccessAllowedAce - ( - pDaclBuf, - ACL_REVISION, - SYNCHRONIZE | READ_CONTROL | MUTANT_QUERY_STATE, - psidEveryone - ); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) __leave; - - /* grant full access to BUILTIN\Administrators */ - nErrCode = RtlAddAccessAllowedAce - ( - pDaclBuf, - ACL_REVISION, - MUTANT_ALL_ACCESS, - psidAdministrators - ); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) __leave; - - /* grant full access to NT AUTHORITY\SYSTEM */ - nErrCode = RtlAddAccessAllowedAce - ( - pDaclBuf, - ACL_REVISION, - MUTANT_ALL_ACCESS, - psidSystem - ); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) __leave; - - /* create the security descriptor */ - nErrCode = RtlCreateSecurityDescriptor - ( - &sdMutexSecurity, - SECURITY_DESCRIPTOR_REVISION - ); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) __leave; - - /* set the descriptor's DACL to the ACL we created */ - nErrCode = RtlSetDaclSecurityDescriptor - ( - &sdMutexSecurity, - TRUE, - pDaclBuf, - FALSE - ); - - /* failure */ - if(!NT_SUCCESS(nErrCode)) __leave; - - /* create the mutex */ - hMutex = CreateMutexW(&saMutexAttribs, FALSE, L"DBWinMutex"); + + /* first, set up the mutex security */ + /* allocate the NT AUTHORITY\SYSTEM SID */ + nErrCode = RtlAllocateAndInitializeSid(&siaNTAuth, + 1, + SECURITY_LOCAL_SYSTEM_RID, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + &psidSystem); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) __leave; + + /* allocate the BUILTIN\Administrators SID */ + nErrCode = RtlAllocateAndInitializeSid(&siaNTAuth, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, + 0, + 0, + 0, + 0, + 0, + &psidAdministrators); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) __leave; + + /* allocate the Everyone SID */ + nErrCode = RtlAllocateAndInitializeSid(&siaWorldAuth, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + &psidEveryone); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) __leave; + + /* allocate space for the SIDs too */ + nDaclBufSize += RtlLengthSid(psidSystem); + nDaclBufSize += RtlLengthSid(psidAdministrators); + nDaclBufSize += RtlLengthSid(psidEveryone); + + /* allocate the buffer for the DACL */ + pDaclBuf = GlobalAlloc(GMEM_FIXED, nDaclBufSize); + + /* failure */ + if(pDaclBuf == NULL) __leave; + + /* create the DACL */ + nErrCode = RtlCreateAcl(pDaclBuf, nDaclBufSize, ACL_REVISION); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) __leave; + + /* grant the minimum required access to Everyone */ + nErrCode = RtlAddAccessAllowedAce(pDaclBuf, + ACL_REVISION, + SYNCHRONIZE | + READ_CONTROL | + MUTANT_QUERY_STATE, + psidEveryone); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) __leave; + + /* grant full access to BUILTIN\Administrators */ + nErrCode = RtlAddAccessAllowedAce(pDaclBuf, + ACL_REVISION, + MUTANT_ALL_ACCESS, + psidAdministrators); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) __leave; + + /* grant full access to NT AUTHORITY\SYSTEM */ + nErrCode = RtlAddAccessAllowedAce(pDaclBuf, + ACL_REVISION, + MUTANT_ALL_ACCESS, + psidSystem); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) __leave; + + /* create the security descriptor */ + nErrCode = RtlCreateSecurityDescriptor(&sdMutexSecurity, + SECURITY_DESCRIPTOR_REVISION); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) __leave; + + /* set the descriptor's DACL to the ACL we created */ + nErrCode = RtlSetDaclSecurityDescriptor(&sdMutexSecurity, + TRUE, + pDaclBuf, + FALSE); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) __leave; + + /* create the mutex */ + hMutex = CreateMutexW(&saMutexAttribs, FALSE, L"DBWinMutex"); #if 0 } __finally @@ -222,23 +191,26 @@ #else l_Cleanup: #endif - /* free the buffers */ - if(pDaclBuf) GlobalFree(pDaclBuf); - if(psidEveryone) RtlFreeSid(psidEveryone); - if(psidAdministrators) RtlFreeSid(psidAdministrators); - if(psidSystem) RtlFreeSid(psidSystem); + + /* 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; }
/* * @implemented */ -VOID WINAPI OutputDebugStringA(LPCSTR _OutputString) +VOID +WINAPI +OutputDebugStringA(LPCSTR _OutputString) { #if 0 /* FIXME: this will be pointless until GCC does SEH */ @@ -255,99 +227,91 @@ __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; - } + + /* 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 - { + + /* 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"); + /* 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); + /* 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 @@ -356,76 +320,75 @@ do #endif { - /* size of the current output block */ - SIZE_T nRoundLen; - /* size of the remainder of the string */ - SIZE_T nOutputStringLen; - - for - ( - /* output the whole string */ - nOutputStringLen = strlen(_OutputString); - /* repeat until the string has been fully output */ - nOutputStringLen > 0; - /* move to the next block */ - _OutputString += nRoundLen, nOutputStringLen -= nRoundLen - ) - { - /* - 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) - 1)) - nRoundLen = sizeof(a_cBuffer) - 1; - 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); - } + /* size of the current output block */ + SIZE_T nRoundLen; + + /* size of the remainder of the string */ + SIZE_T nOutputStringLen; + + for + ( + /* output the whole string */ + nOutputStringLen = strlen(_OutputString); + + /* repeat until the string has been fully output */ + nOutputStringLen > 0; + + /* move to the next block */ + _OutputString += nRoundLen, nOutputStringLen -= nRoundLen + ) + { + /* 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) - 1)) + nRoundLen = sizeof(a_cBuffer) - 1; + 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); + } } } #if 0 @@ -449,15 +412,17 @@ __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); + + /* 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 } } @@ -468,32 +433,29 @@ /* * @implemented */ -VOID WINAPI OutputDebugStringW(LPCWSTR _OutputString) +VOID +WINAPI +OutputDebugStringW(LPCWSTR _OutputString) { - UNICODE_STRING wstrOut; - ANSI_STRING strOut; - NTSTATUS nErrCode; - - /* convert the string in ANSI */ - RtlInitUnicodeString(&wstrOut, _OutputString); - nErrCode = RtlUnicodeStringToAnsiString(&strOut, &wstrOut, TRUE); - - 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); - } + UNICODE_STRING wstrOut; + ANSI_STRING strOut; + NTSTATUS nErrCode; + + /* convert the string in ANSI */ + RtlInitUnicodeString(&wstrOut, _OutputString); + nErrCode = RtlUnicodeStringToAnsiString(&strOut, &wstrOut, TRUE); + + 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); + } } - -/* EOF */