//+-------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1996-1996 // // File: mailslot.cpp // // Contents: // // History: // // Note: //--------------------------------------------------------------------------- #include "pch.cpp" #include #include #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; }