/* * pseudocode for OutputDebugString * * from KERNEL32.DLL ver 5.0.2195.6794 * * Reverse engineered by Steve Friedl (steve@unixwiz.net) */ void OutputDebugStringA(LPTSTR *lpString) { DBWIN_buffer *pDBBuffer = 0; HANDLE hFileMap = 0; HANDLE hBufferEvent = 0; HANDLE hDataEvent = 0; // if we can't make or acquire the mutex, we're done if ( hDbwinMutex == 0 ) hDbwinMutex = setup_mutex(); if ( hDbwinMutex == 0) return; (void) WaitForSingleObject(hDbwinMutex, INFINITE); hFileMap = OpenFileMapping(FILE_MAP_WRITE, FALSE, "DBWIN_BUFFER"); pDBBuffer = (DBWIN_buffer *) MapViewOfFile( hFileMap, FILE_MAP_READ|FILE_MAP_WRITE, 0, // file offset high 0, // file offset low 0 ); // # of bytes to map (entire file) hBufferEvent = OpenEvent( SYNCHRONIZE, FALSE, "DBWIN_BUFFER_READY"); hDataEvent = OpenEvent( EVENT_MODIFY_STATE, FALSE, "DBWIN_DATA_READY"); const char *p = lpString; int len = strlen(lpString); while ( len > 0 ) { if ( WaitForSingleObject(hBufferEvent, 10*1000) != WAIT_OBJECT_0 ) { /* ERROR: give up */ break; } // populate the shared memory segment. The string // is limited to 4k or so. pBuffer->dwProcessId = GetCurrentProcessId(); int n = min(len, sizeof(pBuffer->data)-1); memcpy(pBuffer->data, p, n); pBuffer->data[n] = '\0'; len -= n; p += n; SetEvent(hDataEvent); } // cleanup after ourselves CloseHandle(hBufferEvent); CloseHandle(hDataEvent); UnmapViewOfFile(pDBBuffer); CloseHandle(hFileMap); } HANDLE setup_mutex(void) { SID_IDENTIFIER_AUTHORITY SIAWindowsNT = SECURITY_NT_AUTHORITY; SID_IDENTIFIER_AUTHORITY SIAWorld = SECURITY_WORLD_SID_AUTHORITY; SID *pSidSYSTEM = 0, // *pSidAdmins = 0, *pSidEveryone = 0; AllocateAndInitializeSid(&SIAWindowsNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSidSYSTEM); AllocateAndInitializeSid(&SIAWindowsNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSidAdmins); AllocateAndInitializeSid(&SIAWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pSidEveryone); const DWORD dwACLSize = GetLengthSid(pSidSYSTEM) + GetLengthSig(pSidAdmins) + GetLengthSig(pSidEveryone) + 32; ACL *pACL = GlobalAlloc( 0, dwACLSize ); InitializeAcl(pACL, dwACLsize, ACL_REVISION ); AddAccessAllowedAce(pACL, ACL_REVISION, SYNCHRONIZE | READ_CONTROL | MUTEX_QUERY_STATE, pSidEveryone); AddAccessAllowedAce(pACL, ACL_REVISION, MUTEX_ALL_ACCESS, pSidSYSTEM); AddAccessAllowedAce(pACL, ACL_REVISION, MUTEX_ALL_ACCESS, pSidAdmins); SECURITY_DESCRIPTOR sd; InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(&sd, TRUE, pACL, FALSE); SECURITY_ATTRIBUTES sa; ZeroMemory(&sa, sizeof sa); sa.bInheritHandle = FALSE; sa.nLength = sizeof sa; sa.lpSecurityDescriptor = &sd; HANDLE hMutex = CreateMutex(&sa, FALSE, "DBWinMutex"); FreeSid(pSidAdmins); FreeSid(pSidSYSTEM); FreeSid(pSidEveryone); GlobalFree(pACL); return hMutex; }