📄 staflocalipcconnprovider.cpp
字号:
connData.connFunc = provider->connFunc; connData.provider = provider; connData.connection = new STAFLocalConnectionImpl(connImpl); provider->threadManager->dispatch( STAFLocalIPCConnectionThread, new LocalConnectionData(connData)); } } else { // Set up variables into shared memory DWORD *pidSwap = (DWORD *)provider->sharedMem; HANDLE *readHandlePtr = (HANDLE *)((char *)provider->sharedMem + (2 * sizeof(DWORD))); HANDLE *writeHandlePtr = (HANDLE *)((char *)provider->sharedMem + (2 * sizeof(DWORD)) + sizeof(HANDLE)); while (provider->state == kSTAFConnectionProviderActive) { // XXX: See if there is any positive gain by moving the // definitions of these 3 variables outside the while loop HANDLE clientReadHandle = 0; HANDLE clientWriteHandle = 0; HANDLE clientProcess = 0; WaitForMultipleObjects(1, &provider->serverSynch, TRUE, INFINITE); if (provider->state != kSTAFConnectionProviderActive) break; // XXX: Temp until auto-reset event sem done ResetEvent(provider->serverSynch); clientProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, *pidSwap); if (clientProcess == 0) HANDLE_SHAREDMEM_RUN_ERROR("OpenProcess2()"); // Create ServerRead/ClientWrite pipe if (!CreatePipe(&connImpl.readHandle, &clientWriteHandle, 0, 0x00000400)) { HANDLE_SHAREDMEM_RUN_ERROR("CreatePipe()"); } // Create ServerWrite/ClientRead pipe if (!CreatePipe(&clientReadHandle, &connImpl.writeHandle, 0, 0x00000400)) { HANDLE_SHAREDMEM_RUN_ERROR("CreatePipe()"); } if (!DuplicateHandle(GetCurrentProcess(), clientReadHandle, clientProcess, readHandlePtr, 0, FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) { HANDLE_SHAREDMEM_RUN_ERROR("DuplicateHandle(readHandle)"); } if (!DuplicateHandle(GetCurrentProcess(), clientWriteHandle, clientProcess, writeHandlePtr, 0, FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) { HANDLE_SHAREDMEM_RUN_ERROR("DuplicateHandle(writeHandle)"); } CloseHandle(clientProcess); SetEvent(provider->clientSynch); // Ok, let's perform the callback now LocalConnectionData connData; connData.connFunc = provider->connFunc; connData.provider = provider; connData.connection = new STAFLocalConnectionImpl(connImpl); provider->threadManager->dispatch( STAFLocalIPCConnectionThread, new LocalConnectionData(connData)); } } } CATCH_STANDARD_TRACE("STAFLocalIPCRunThread"); if (sd != 0) STAFUtilWin32DeleteNullSD(&sd); try { provider->syncSem->post(); } CATCH_STANDARD_TRACE("STAFLocalIPCRunThread"); return 0;}//============ Shared Memory Only Functions ==================================// These functions are only used if using shared memory (not when using// named pipes as the ipcMethod) #define HANDLE_PIPEDATA_ERROR(string) \HANDLE_PIPEDATA_ERROR2(string, GetLastError())#define HANDLE_PIPEDATA_ERROR2(string, error) \{\ STAFString theError = STAFString(string) + ", RC=" + STAFString(error);\\ if (errorBuffer) *errorBuffer = theError.adoptImpl();\ if (sd != 0) STAFUtilWin32DeleteNullSD(&sd);\ if (sharedMem != 0) UnmapViewOfFile(sharedMem);\ if (fileMap != 0) CloseHandle(fileMap);\ if (pipeData.clientMutex != 0) CloseHandle(pipeData.clientMutex);\ if (pipeData.serverSynchSem != 0) CloseHandle(pipeData.serverSynchSem);\ if (pipeData.clientSynchSem != 0) CloseHandle(pipeData.clientSynchSem);\\ return;\}// Note: You should already own sPipeMapSem before calling this functionstatic void GetPipeData(const STAFString &pipeName, PipeData &pipeData, STAFString_t *errorBuffer){ PipeMap::iterator iter; if ((iter = sPipeMap.find(pipeName)) == sPipeMap.end()) { HANDLE fileMap = 0; void *sharedMem = 0; DWORD *serverPID = 0; SECURITY_ATTRIBUTES sa; PSECURITY_DESCRIPTOR sd = 0; STAFString globalStr = ""; if (STAFUtilWin32GetWinType() & kSTAFWin2KPlus) { // Open Process to get process handle and SetSecurityInfo HANDLE pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()); if (pHandle == 0) HANDLE_PIPEDATA_ERROR("First OpenProcess()"); int rc = SetSecurityInfo(pHandle, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, 0, 0); if (rc != 0) HANDLE_PIPEDATA_ERROR2("SetSecurityInfo()", rc); // To support Fast User Switching and Terminal Server need // to prepend Global\\ for Win2K and above. globalStr = "Global\\"; } STAFString sharedMemName = globalStr + pipeName + "/SharedMemory"; // Obtain Shared Memory fileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, sharedMemName.toCurrentCodePage()->buffer()); if (fileMap == 0) HANDLE_PIPEDATA_ERROR("OpenFileMapping()"); sharedMem = MapViewOfFile(fileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (sharedMem == 0) HANDLE_PIPEDATA_ERROR("MapViewOfFile()"); // Set up security attributes sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = sd; // Create Null Security Descriptor to allow access to everyone if (STAFUtilWin32CreateNullSD(&sd)) HANDLE_PIPEDATA_ERROR("STAFUtilWin32CreateNullSD()"); sa.lpSecurityDescriptor = sd; // Get initialization semaphores STAFString clientMutexName = globalStr + pipeName + "/ClientMutex"; STAFString serverSynchName = globalStr + pipeName + "/ServerSynch"; STAFString clientSynchName = globalStr + pipeName + "/ClientSynch"; pipeData.clientMutex = CreateMutex(&sa, FALSE, clientMutexName.toCurrentCodePage()->buffer()); if (pipeData.clientMutex == 0) HANDLE_PIPEDATA_ERROR("CreateMutex()"); pipeData.serverSynchSem = CreateEvent(&sa, TRUE, FALSE, serverSynchName.toCurrentCodePage()->buffer()); if (pipeData.serverSynchSem == 0) HANDLE_PIPEDATA_ERROR("CreateEvent()"); pipeData.clientSynchSem = CreateEvent(&sa, TRUE, FALSE, clientSynchName.toCurrentCodePage()->buffer()); if (pipeData.clientSynchSem == 0) HANDLE_PIPEDATA_ERROR("CreateEvent()"); // Set up some pointers into the shared memory area pipeData.pidSwap = (DWORD *)sharedMem; serverPID = (DWORD *)((char *)sharedMem + sizeof(DWORD)); pipeData.readHandlePtr = (HANDLE *)((char *)sharedMem + (2 *sizeof(DWORD))); pipeData.writeHandlePtr = (HANDLE *)((char *)sharedMem + (2 * sizeof(DWORD)) + sizeof(HANDLE)); // Obtain handle to Factory process pipeData.serverProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, *serverPID); if (pipeData.serverProcessHandle == 0) HANDLE_PIPEDATA_ERROR("Second OpenProcess()"); sPipeMap[pipeName] = pipeData; if (sd != 0) STAFUtilWin32DeleteNullSD(&sd); } else pipeData = iter->second;}#define HANDLE_PIPECONNECT_ERROR(string) \HANDLE_PIPECONNECT_ERROR2(string, GetLastError())#define HANDLE_PIPECONNECT_ERROR2(string, error) \{\ STAFString theError = STAFString(string) + STAFString(error);\\ if (errorBuffer) *errorBuffer = theError.adoptImpl();\\ return false;\}// True = successfully connected, False = server process disappeared// Note: This function can still throw exceptionsstatic bool ConnectToPipe(PipeData &pipeData, HANDLE &readHandle, HANDLE &writeHandle, STAFString_t *errorBuffer){ // Obtain the client mutex on this "named pipe", while we swap // process information with the STAFLocalConnectionFactory WaitForSingleObject(pipeData.clientMutex, INFINITE); *pipeData.pidSwap = GetCurrentProcessId(); ResetEvent(pipeData.clientSynchSem); SetEvent(pipeData.serverSynchSem); HANDLE waitArray[2] = { pipeData.clientSynchSem, pipeData.serverProcessHandle }; DWORD rc = WaitForMultipleObjects(2, waitArray, FALSE, INFINITE); unsigned int signaledHandleIndex = 0; if ((rc >= WAIT_OBJECT_0) && (rc <= (WAIT_OBJECT_0 + 2 - 1))) { signaledHandleIndex = (unsigned int)(rc - WAIT_OBJECT_0); } else if ((rc >= WAIT_ABANDONED_0) && (rc <= (WAIT_ABANDONED_0 + 2 - 1))) { signaledHandleIndex = (unsigned int)(rc - WAIT_ABANDONED_0); } else { // We either got WAIT_FAILED, WAIT_TIMEOUT or some other return // code which we weren't expecting, so spit out an error message // and continue ReleaseMutex(pipeData.clientMutex); HANDLE_PIPECONNECT_ERROR2("Other side closed connection", rc); } if (signaledHandleIndex != 0) { ReleaseMutex(pipeData.clientMutex); return false; } if (pipeData.pidSwap == 0) { ReleaseMutex(pipeData.clientMutex); HANDLE_PIPECONNECT_ERROR("Other side closed connection"); } readHandle = *pipeData.readHandlePtr; writeHandle = *pipeData.writeHandlePtr; ReleaseMutex(pipeData.clientMutex); return true;}//========= End Shared Memory Only Functions =================================STAFRC_t STAFConnectionProviderConstruct(STAFConnectionProvider_t *provider, void *constructInfo, unsigned int constructInfoLevel, STAFString_t *errorBuffer){ if (provider == 0) return kSTAFInvalidParm; if (constructInfoLevel != 1) return kSTAFInvalidAPILevel; STAFConnectionProviderConstructInfoLevel1 *cpInfo = reinterpret_cast<STAFConnectionProviderConstructInfoLevel1 *>( constructInfo); try { static bool initedAtExit = false; if (!initedAtExit) { STAFMutexSemLock lock(sActiveProvidersSem); if (!initedAtExit) atexit(atExit); } STAFLocalConnectionProviderImpl lipcData; lipcData.mode = cpInfo->mode; lipcData.syncSem = STAFEventSemPtr( new STAFEventSem, STAFEventSemPtr::INIT); lipcData.state = kSTAFConnectionProviderStopped; lipcData.ipcName = "STAF"; lipcData.threadManager = STAFThreadManagerPtr( new STAFThreadManager, STAFThreadManagerPtr::INIT); // The Windows local connection provider supports two methods for // handling interprocess communication (IPC): // 1) Shared memory // 2) Named pipes // // Notes: // - Windows Me/98/95 cannot create named pipes so the shared memory // IPC method must be used. // - Windows Vista with UAC enabled cannot use global shared memory // so the named pipes method must be used. // - The performance using either of these methods is equivalent. // So, we chose to continue to use shared memory for pre-Vista // machines (though we could have selected to use named pipes for // Windows NT and later) and we are using named pipes for Vista // and future Windows versions. if (STAFUtilWin32GetWinType() & kSTAFWinVistaPlus) lipcData.ipcMethod = kNamedPipes; else lipcData.ipcMethod = kSharedMemory; // Get instance name if (getenv("STAF_INSTANCE_NAME") != NULL) { lipcData.ipcName = getenv("STAF_INSTANCE_NAME"); } for (unsigned int i = 0; i < cpInfo->numOptions; ++i) { STAFString thisOption = STAFString(cpInfo->optionNames[i]).upperCase(); if (thisOption == "IPCNAME") { lipcData.ipcName += cpInfo->optionValues[i]; } else { if (errorBuffer) { *errorBuffer = STAFString(cpInfo->optionNames[i]).adoptImpl(); } return kSTAFInvalidValue; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -