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.
 
 
 
 
 
 

513 lines
13 KiB

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996-1996
//
// File: mailslot.cpp
//
// Contents:
//
// History:
//
// Note:
//---------------------------------------------------------------------------
#include "pch.cpp"
#include <tchar.h>
#include <process.h>
#include "lscommon.h"
#include "debug.h"
#include "globals.h"
typedef DWORD (* LSPROTOCOLHANDLER)(DWORD cbData, PBYTE pbData);
typedef struct _ProtocolFuncMapper {
LPTSTR szProtocol;
LSPROTOCOLHANDLER func;
} ProtocolFuncMapper;
DWORD HandleDiscovery( DWORD cbData, PBYTE pbData );
DWORD HandleChallenge( DWORD cbData, PBYTE pbData );
ProtocolFuncMapper pfm[] = {
{_TEXT(LSERVER_DISCOVERY), HandleDiscovery},
{_TEXT(LSERVER_CHALLENGE), HandleChallenge}
};
DWORD dwNumProtocol=sizeof(pfm) / sizeof(pfm[0]);
//--------------------------------------------------------------------
DWORD
HandleDiscovery(
DWORD cbData,
PBYTE pbData
)
/*++
++*/
{
TCHAR szDiscMsg[MAX_MAILSLOT_MSG_SIZE+1];
TCHAR szPipeName[MAX_MAILSLOT_MSG_SIZE+20];
TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH+2];
DWORD cbComputerName = MAX_COMPUTERNAME_LENGTH+1;
DWORD byteWritten = 0;
LPTSTR pClientName;
LPTSTR pMailSlot;
LPTSTR ePtr;
DWORD dwStatus=ERROR_SUCCESS;
HANDLE hSlot = INVALID_HANDLE_VALUE;
DWORD dwFileType;
if(cbData >= sizeof(szDiscMsg)-sizeof(TCHAR))
{
dwStatus = ERROR_INVALID_PARAMETER;
return dwStatus;
}
//
// Prevent no NULL terminated input
//
memset(szDiscMsg, 0, sizeof(szDiscMsg));
memcpy(szDiscMsg, pbData, cbData);
GetComputerName(szComputerName, &cbComputerName);
do {
//
// Extract client machine name
//
pClientName=_tcschr(szDiscMsg, _TEXT(LSERVER_OPEN_BLK));
if(pClientName == NULL)
{
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("Can't find beginning client name\n")
);
dwStatus = ERROR_INVALID_PARAMETER;
break;
}
pClientName = _tcsinc(pClientName);
ePtr=_tcschr(pClientName, _TEXT(LSERVER_CLOSE_BLK));
if(ePtr == NULL)
{
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("Can't find ending client name\n")
);
dwStatus = ERROR_INVALID_PARAMETER;
break;
}
*ePtr = _TEXT('\0');
//
// Extract Mailslot name
//
ePtr = _tcsinc(ePtr);
pMailSlot = _tcschr(ePtr, _TEXT(LSERVER_OPEN_BLK));
if(pMailSlot == NULL)
{
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("Can't find beginning mailslot name\n")
);
dwStatus = ERROR_INVALID_PARAMETER;
break;
}
pMailSlot = _tcsinc(pMailSlot);
ePtr=_tcschr(pMailSlot, _TEXT(LSERVER_CLOSE_BLK));
if(ePtr == NULL)
{
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("Can't find ending mailslot name\n")
);
dwStatus = ERROR_INVALID_PARAMETER;
break;
}
*ePtr = _TEXT('\0');
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("response to client %s, %s\n"),
pClientName,
pMailSlot
);
//
// Do not respond to "*"
//
if(_tcscmp(pClientName, _TEXT("*")) == 0)
{
dwStatus = ERROR_INVALID_PARAMETER;
break;
}
if (lstrlen(pClientName) + lstrlen(pMailSlot) + 13 > sizeof(szPipeName) / sizeof(TCHAR))
{
dwStatus = ERROR_INVALID_PARAMETER;
break;
}
//
// SECURITY: Must make sure that what we're opening is really a
// mailslot (no tricks with .., extra backslashes, etc.
//
if ((_tcsstr(pClientName,_TEXT("..")) != NULL)
|| (_tcsstr(pMailSlot,_TEXT("..")) != NULL))
{
dwStatus = ERROR_INVALID_PARAMETER;
break;
}
if ((_tcschr(pClientName, _TEXT('\\')) != NULL)
|| (_tcschr(pMailSlot, _TEXT('\\')) != NULL))
{
dwStatus = ERROR_INVALID_PARAMETER;
break;
}
//
// Open client side mailslot
//
wsprintf(
szPipeName,
_TEXT("\\\\%s\\mailslot\\%s"),
pClientName,
pMailSlot
);
if (0 == ImpersonateAnonymousToken(GetCurrentThread()))
{
dwStatus = GetLastError();
break;
}
hSlot = CreateFile(
szPipeName,
GENERIC_WRITE, // only need write
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if(hSlot == INVALID_HANDLE_VALUE)
{
dwStatus = GetLastError();
RevertToSelf();
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("CreateFile %s failed with %d\n"),
szPipeName,
dwStatus
);
break;
}
dwFileType = GetFileType(hSlot);
if ((FILE_TYPE_DISK == dwFileType)
|| (FILE_TYPE_CHAR == dwFileType)
|| (FILE_TYPE_PIPE == dwFileType))
{
//
// This isn't a mailslot!
//
RevertToSelf();
dwStatus = ERROR_INVALID_PARAMETER;
break;
}
//
// Write our computername to client side mailslot
//
if(!WriteFile(hSlot, szComputerName, (_tcslen(szComputerName)+1)*sizeof(TCHAR), &byteWritten, NULL) ||
byteWritten != (_tcslen(szComputerName)+1)*sizeof(TCHAR) )
{
dwStatus = GetLastError();
RevertToSelf();
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("Write to %s failed with %d\n"),
szPipeName,
dwStatus
);
break;
}
RevertToSelf();
} while(FALSE);
if(hSlot != INVALID_HANDLE_VALUE)
{
CloseHandle(hSlot);
}
return dwStatus;
}
//--------------------------------------------------------------------
DWORD
HandleChallenge(
DWORD cbData,
PBYTE pbData
)
/*++
++*/
{
return ERROR_SUCCESS;
}
//---------------------------------------------------------------------
unsigned int WINAPI
MailSlotThread(void* ptr)
{
HANDLE hEvent=(HANDLE) ptr;
DWORD dwStatus=ERROR_SUCCESS;
HANDLE hSlot=INVALID_HANDLE_VALUE;
DWORD cbToRead;
TCHAR szMailSlotName[MAX_PATH+1];
TCHAR szMessage[MAX_MAILSLOT_MSG_SIZE+1];
BOOL fResult=TRUE;
do {
//
// Create the mail slot
//
wsprintf(
szMailSlotName,
_TEXT("\\\\.\\mailslot\\%s"),
_TEXT(SERVERMAILSLOTNAME)
);
hSlot=CreateMailslot(
szMailSlotName,
MAX_MAILSLOT_MSG_SIZE,
MAILSLOT_WAIT_FOREVER,
NULL //&SecurityAttributes
);
if(hSlot == INVALID_HANDLE_VALUE)
{
dwStatus=GetLastError();
break;
}
//
// Signal mail thread we are ready
//
SetEvent(hEvent);
DBGPrintf(
DBG_INFORMATION,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
DBG_ALL_LEVEL,
_TEXT("Mailslot : ready...\n")
);
//
// Forever loop
//
while(dwStatus == ERROR_SUCCESS)
{
memset(szMessage, 0, sizeof(szMessage));
//
// Wait on the Slot - TODO consider using IO completion port.
//
fResult=ReadFile(
hSlot,
szMessage,
sizeof(szMessage) - sizeof(TCHAR),
&cbToRead,
NULL
);
if(!fResult)
{
DBGPrintf(
DBG_ERROR,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_ERROR,
_TEXT("Mailslot : read failed %d\n"),
GetLastError()
);
continue;
}
DBGPrintf(
DBG_INFORMATION,
DBG_FACILITY_RPC,
DBGLEVEL_FUNCTION_DETAILSIMPLE,
_TEXT("Mailslot : receive message %s\n"),
szMessage
);
//
// Process Message
//
for(int i=0; i < dwNumProtocol; i++)
{
if(!_tcsnicmp(szMessage, pfm[i].szProtocol, _tcslen(pfm[i].szProtocol)))
{
(pfm[i].func)( ((DWORD)_tcslen(szMessage) - (DWORD)_tcslen(pfm[i].szProtocol))*sizeof(TCHAR),
(PBYTE)(szMessage + _tcslen(pfm[i].szProtocol)) );
}
}
}
} while (FALSE);
if(hSlot != INVALID_HANDLE_VALUE)
CloseHandle(hSlot);
//
// Mail thread will close the event handle
//
ExitThread(dwStatus);
return dwStatus;
}
//---------------------------------------------------------------------
DWORD
InitMailSlotThread()
/*++
++*/
{
HANDLE hThread = NULL;
unsigned int dwThreadId;
HANDLE hEvent = NULL;
DWORD dwStatus = ERROR_SUCCESS;
HANDLE waithandles[2];
//
// Create a event for namedpipe thread to signal it is ready.
//
hEvent = CreateEvent(
NULL,
FALSE,
FALSE, // non-signal
NULL
);
if(hEvent == NULL)
{
dwStatus = GetLastError();
goto cleanup;
}
hThread = (HANDLE)_beginthreadex(
NULL,
0,
MailSlotThread,
hEvent,
0,
&dwThreadId
);
if(hThread == NULL)
{
dwStatus = GetLastError();
goto cleanup;
}
waithandles[0] = hEvent;
waithandles[1] = hThread;
//
// Wait 30 second for thread to complet initialization
//
dwStatus = WaitForMultipleObjects(
sizeof(waithandles)/sizeof(waithandles[0]),
waithandles,
FALSE,
30*1000
);
if(dwStatus == WAIT_OBJECT_0)
{
//
// thread is ready
//
dwStatus = ERROR_SUCCESS;
}
else
{
if(dwStatus == (WAIT_OBJECT_0 + 1))
{
//
// Thread terminate abnormally
//
GetExitCodeThread(
hThread,
&dwStatus
);
}
else
{
dwStatus = TLS_E_SERVICE_STARTUP_CREATE_THREAD;
}
}
cleanup:
if(hEvent != NULL)
{
CloseHandle(hEvent);
}
if(hThread != NULL)
{
CloseHandle(hThread);
}
return dwStatus;
}