Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

570 lines
13 KiB

/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
ipc.cpp
Abstract:
Implements code that communicates with shimeng to get the debug spew.
On xpsp1 and beyong we get the debug info spewed by OutputDebugString.
On the older platforms we use named pipes to communicate with shimeng.
Notes:
Unicode only.
History:
04/22/2002 maonis Created
--*/
#include "precomp.h"
extern APPINFO g_ai;
// These are the only types of objects we created.
typedef enum _SHIMVIEW_OBJECT_TYPE
{
SHIMVIEW_EVENT = 0,
SHIMVIEW_FILE_MAPPING,
SHIMVIEW_NAMED_PIPE
} SHIMVIEW_OBJECT_TYPE;
//
// Stuff we need for the new version.
//
#define SHIMVIEW_SPEW_LEN 2048
#define DEBUG_SPEW_DATA_PREFIX "SHIMVIEW:"
#define DEBUG_SPEW_DATA_PREFIX_LEN (sizeof(DEBUG_SPEW_DATA_PREFIX)/sizeof(CHAR) - 1)
LPSTR g_pDebugSpew;
HANDLE g_hReadyEvent;
HANDLE g_hAckEvent;
/*++
Routine Description:
Creates a security descriptor that gives Everyone read and write access
to the object itself, ie, we don't include permissions like WRITE_OWNER
or WRITE_DAC.
The resulting security descriptor should be freed by the caller using
free.
Arguments:
eObjectType - the object type.
Return Value:
NULL on failure, a valid security descriptor on success.
--*/
PSECURITY_DESCRIPTOR
CreateShimViewSd(
SHIMVIEW_OBJECT_TYPE eObjectType
)
{
BOOL bIsSuccess = FALSE;
PSID pWorldSid = NULL;
PSECURITY_DESCRIPTOR pWorldSd = NULL;
DWORD dwAclSize = 0;
PACL pAcl = NULL;
DWORD dwAccessMask = 0;
SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
if (!AllocateAndInitializeSid(&WorldSidAuthority,
1,
SECURITY_WORLD_RID,
0, 0, 0, 0, 0, 0, 0,
&pWorldSid)) {
MessageBox(NULL, L"Failed to allocate a SID", L"Error!", MB_ICONERROR);
goto cleanup;
}
dwAclSize =
sizeof (ACL) +
sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD) +
GetLengthSid(pWorldSid);
pWorldSd = (PSECURITY_DESCRIPTOR)malloc(SECURITY_DESCRIPTOR_MIN_LENGTH + dwAclSize);
if (pWorldSd == NULL) {
MessageBox(
NULL,
L"Failed to allocate memory for the security descriptor",
L"Error",
MB_ICONERROR);
goto cleanup;
}
pAcl = (PACL)((BYTE *)pWorldSd + SECURITY_DESCRIPTOR_MIN_LENGTH);
if (!InitializeAcl(pAcl,
dwAclSize,
ACL_REVISION)) {
MessageBox(
NULL,
L"Failed to allocate memory for the security descriptor",
L"Error",
MB_ICONERROR);
goto cleanup;
}
switch (eObjectType) {
case SHIMVIEW_EVENT:
dwAccessMask = READ_CONTROL | SYNCHRONIZE | EVENT_MODIFY_STATE;
break;
case SHIMVIEW_FILE_MAPPING:
dwAccessMask = FILE_MAP_READ | FILE_MAP_WRITE;
break;
case SHIMVIEW_NAMED_PIPE:
dwAccessMask = GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE;
break;
default:
MessageBox(
NULL,
L"You specified an unknown object type to create the security descriptor",
L"Error",
MB_ICONERROR);
goto cleanup;
}
if (!AddAccessAllowedAce(pAcl,
ACL_REVISION,
dwAccessMask,
pWorldSid)) {
MessageBox(
NULL,
L"Failed to add the ACE to the security descriptor",
L"Error",
MB_ICONERROR);
goto cleanup;
}
if (!InitializeSecurityDescriptor(pWorldSd, SECURITY_DESCRIPTOR_REVISION) ||
!SetSecurityDescriptorDacl(pWorldSd, TRUE, pAcl, FALSE)) {
MessageBox(
NULL,
L"Failed to set the DACL for the security descriptor",
L"Error",
MB_ICONERROR);
goto cleanup;
}
bIsSuccess = TRUE;
cleanup:
if (pWorldSid) {
FreeSid(pWorldSid);
}
if (!bIsSuccess) {
if (pWorldSd) {
free(pWorldSd);
pWorldSd = NULL;
}
}
return pWorldSd;
}
void
AddSpewW(
LPCWSTR pwszBuffer
)
{
WCHAR* pTemp = NULL;
//
// See if this is a new process notification.
//
pTemp = wcsstr(pwszBuffer, L"process");
if (pTemp) {
//
// We got a new process notification.
// See if any items are already in the list
//
if (ListView_GetItemCount(g_ai.hWndList)) {
AddListViewItem(L"");
}
}
AddListViewItem((LPWSTR)pwszBuffer);
}
void
AddSpewA(
LPCSTR pszBuffer
)
{
int iChars = 0;
LPWSTR pwszBuffer = NULL;
iChars = MultiByteToWideChar(CP_ACP, 0, pszBuffer, -1, NULL, 0);
if (iChars) {
pwszBuffer = (LPWSTR)malloc(iChars * sizeof(WCHAR));
if (pwszBuffer) {
if (MultiByteToWideChar(CP_ACP, 0, pszBuffer, -1, pwszBuffer, iChars)) {
pwszBuffer[iChars - 1] = 0;
AddSpewW(pwszBuffer);
}
free(pwszBuffer);
}
}
}
/*++
Routine Description:
Thread callback responsible for receiving data from the client.
Arguments:
*pVoid - A handle to the pipe.
Return Value:
-1 on failure, 1 on success.
--*/
UINT
InstanceThread(
IN void* pVoid
)
{
HANDLE hPipe;
BOOL fSuccess = TRUE;
DWORD cbBytesRead = 0;
WCHAR wszBuffer[SHIMVIEW_SPEW_LEN];
//
// The pipe handle was passed as an argument.
//
hPipe = (HANDLE)pVoid;
while (TRUE) {
fSuccess = ReadFile(hPipe,
wszBuffer,
SHIMVIEW_SPEW_LEN * sizeof(WCHAR),
&cbBytesRead,
NULL);
if (!fSuccess || cbBytesRead == 0) {
break;
}
wszBuffer[cbBytesRead / sizeof(WCHAR)] = 0;
AddSpewW(wszBuffer);
}
//
// Flush the pipe to allow the client to read the pipe's contents
// before disconnecting. Then disconnect the pipe, and close the
// handle to this pipe instance.
//
FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
return 1;
}
/*++
Routine Description:
Creates a pipe and listens for messages from the client.
This code is modified from the pipe.cpp that was sd deleted.
Arguments:
None.
Return Value:
-1 on failure, 0 on success.
--*/
UINT
CreatePipeAndWait()
{
HANDLE hPipe, hThread;
BOOL fConnected = FALSE;
while (g_ai.fMonitor) {
//
// Create the named pipe.
//
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, FALSE};
PSECURITY_DESCRIPTOR pSd = CreateShimViewSd(SHIMVIEW_NAMED_PIPE);
if (pSd == NULL) {
return -1;
}
sa.lpSecurityDescriptor = pSd;
hPipe = CreateNamedPipe(PIPE_NAME, // pipe name
PIPE_ACCESS_INBOUND, // read access
PIPE_TYPE_MESSAGE | // message type pipe
PIPE_READMODE_MESSAGE | // message-read mode
PIPE_WAIT, // blocking mode
PIPE_UNLIMITED_INSTANCES, // max. instances
0, // output buffer size
SHIMVIEW_SPEW_LEN, // input buffer size
0, // client time-out
&sa); // no security attribute
free(pSd);
if (INVALID_HANDLE_VALUE == hPipe) {
return -1;
}
//
// Wait for clients to connect.
//
fConnected = ConnectNamedPipe(hPipe, NULL) ?
TRUE :
(GetLastError() == ERROR_PIPE_CONNECTED);
if (fConnected && g_ai.fMonitor) {
hThread = (HANDLE)_beginthreadex(NULL,
0,
&InstanceThread,
(LPVOID)hPipe,
0,
&g_ai.uInstThreadId);
if (INVALID_HANDLE_VALUE == hThread) {
return -1;
} else {
CloseHandle(hThread);
}
} else {
CloseHandle(hPipe);
}
}
return 0;
}
/*++
Routine Description:
Waits for the spew from OutputDebugString and add it to the listview.
Code is modified from the dbmon source.
Arguments:
None.
Return Value:
-1 on failure, 0 on success.
--*/
UINT
GetOutputDebugStringSpew()
{
DWORD dwRet;
while (TRUE) {
dwRet = WaitForSingleObject(g_hReadyEvent, INFINITE);
if (dwRet != WAIT_OBJECT_0) {
return -1;
} else {
if (g_ai.fMonitor &&
!strncmp(g_pDebugSpew,
DEBUG_SPEW_DATA_PREFIX,
DEBUG_SPEW_DATA_PREFIX_LEN)) {
//
// Only add when it came from shimeng.
//
AddSpewA(g_pDebugSpew + DEBUG_SPEW_DATA_PREFIX_LEN);
}
SetEvent(g_hAckEvent);
}
}
return 0;
}
/*++
Routine Description:
Creates the necessary objects to get the spew from OutputDebugString.
Code is modified from the dbmon source.
Arguments:
None.
Return Value:
FALSE on failure, TRUE on success.
--*/
BOOL
CreateDebugObjects(
void
)
{
SECURITY_ATTRIBUTES saEvent = {sizeof(SECURITY_ATTRIBUTES), NULL, FALSE};
SECURITY_ATTRIBUTES saFileMapping = {sizeof(SECURITY_ATTRIBUTES), NULL, FALSE};
PSECURITY_DESCRIPTOR pSdEvent = NULL;
PSECURITY_DESCRIPTOR pSdFileMapping = NULL;
HANDLE hSharedFile;
LPVOID pSharedMem;
BOOL bReturn = FALSE;
pSdEvent = CreateShimViewSd(SHIMVIEW_EVENT);
if (pSdEvent == NULL) {
goto cleanup;
}
pSdFileMapping = CreateShimViewSd(SHIMVIEW_FILE_MAPPING);
if (pSdFileMapping == NULL) {
goto cleanup;
}
saEvent.lpSecurityDescriptor = pSdEvent;
saFileMapping.lpSecurityDescriptor = pSdFileMapping;
g_hAckEvent = CreateEvent(&saEvent, FALSE, FALSE, L"DBWIN_BUFFER_READY");
if (g_hAckEvent == NULL) {
goto cleanup;
}
g_hReadyEvent = CreateEvent(&saEvent, FALSE, FALSE, L"DBWIN_DATA_READY");
if (g_hReadyEvent == NULL) {
goto cleanup;
}
hSharedFile = CreateFileMapping((HANDLE)-1,
&saFileMapping,
PAGE_READWRITE,
0,
4096,
L"DBWIN_BUFFER");
if (hSharedFile == NULL) {
goto cleanup;
}
pSharedMem = MapViewOfFile(hSharedFile,
FILE_MAP_READ,
0,
0,
512);
if (pSharedMem == NULL) {
goto cleanup;
}
g_pDebugSpew = (LPSTR)pSharedMem + sizeof(DWORD);
SetEvent(g_hAckEvent);
bReturn = TRUE;
cleanup:
if (pSdEvent) {
free(pSdEvent);
}
if (pSdFileMapping) {
free(pSdFileMapping);
}
return bReturn;
}
UINT
GetSpewProc(
IN void* pVoid
)
{
if (g_ai.bUsingNewShimEng) {
return GetOutputDebugStringSpew();
} else {
return CreatePipeAndWait();
}
}
/*++
Routine Description:
Check the version of the OS - for 5.2 and beyong shimeng outputs debug spew via
OutputDebugString. For OS version < 5.2 it writes to the named pipe.
Arguments:
None.
Return Value:
TRUE on success, FALSE otherwise.
--*/
BOOL
CreateReceiveThread(
void
)
{
HANDLE hThread;
hThread = (HANDLE)_beginthreadex(NULL,
0,
&GetSpewProc,
NULL,
0,
&g_ai.uThreadId);
CloseHandle(hThread);
return TRUE;
}