📄 staflocalipcconnprovider.cpp
字号:
} // Add each option to a map. lipcData.options = STAFObject::createMap(); lipcData.options->put("IPCName", lipcData.ipcName); if (lipcData.ipcMethod == kNamedPipes) lipcData.options->put("IPCMethod", STAFString("Named pipes")); else lipcData.options->put("IPCMethod", STAFString("Shared memory")); // Setup property values lipcData.portProperty = STAFString(); lipcData.isSecureProperty = STAFString("0"); // Assign logical and physical identifiers lipcData.logicalNetworkID = STAFString("local"); lipcData.physicalNetworkID = STAFString("local"); *provider = new STAFLocalConnectionProviderImpl(lipcData); STAFMutexSemLock lock(sActiveProvidersSem); sActiveProviders.insert(*provider); return kSTAFOk; } CATCH_STANDARD("STAFConnectionProviderConstruct"); return kSTAFUnknownError;}#define HANDLE_START_ERROR(string) HANDLE_START_ERROR2(string, GetLastError())#define HANDLE_START_ERROR2(string, error) \{\ STAFString theError = STAFString(string) + ", RC=" + STAFString(error);\\ if (sd != 0) STAFUtilWin32DeleteNullSD(&sd);\ if (provider->ipcMethod == kSharedMemory)\ {\ if (provider->sharedMem != 0) UnmapViewOfFile(provider->sharedMem);\ if (provider->fileMap != 0) CloseHandle(provider->fileMap);\ }\\ if (errorBuffer) *errorBuffer = theError.adoptImpl();\ return kSTAFBaseOSError;\}STAFRC_t STAFConnectionProviderStart(STAFConnectionProvider_t baseProvider, void *startInfo, unsigned int startInfoLevel, STAFString_t *errorBuffer){ if (baseProvider == 0) return kSTAFInvalidObject; if (startInfoLevel != 1) return kSTAFInvalidAPILevel; STAFConnectionProviderStartInfoLevel1 *cpInfo = reinterpret_cast<STAFConnectionProviderStartInfoLevel1 *>(startInfo); try { if (cpInfo->newConnectionFunc == 0) return kSTAFInvalidValue; STAFLocalConnectionProviderImpl *provider = static_cast<STAFLocalConnectionProviderImpl *>(baseProvider); SECURITY_ATTRIBUTES sa; PSECURITY_DESCRIPTOR sd = 0; // Set up security attributes sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = sd; // Create a Null Security Descriptor to allow access to everyone. if (STAFUtilWin32CreateNullSD(&sd)) HANDLE_START_ERROR("STAFUtilWin32CreateNullSD()"); sa.lpSecurityDescriptor = sd; provider->connFunc = cpInfo->newConnectionFunc; provider->data = cpInfo->data; if (provider->ipcMethod == kNamedPipes) { // Verify that a named pipe can be created successfully STAFString pipeName = PIPENAME_PREFIX + "Test" + provider->ipcName; HANDLE hPipe = CreateNamedPipe( pipeName.toCurrentCodePage()->buffer(), PIPE_ACCESS_DUPLEX, // read/write access PIPE_TYPE_BYTE | // byte type pipe PIPE_READMODE_BYTE | // byte-read mode PIPE_WAIT, // blocking mode PIPE_UNLIMITED_INSTANCES, // max. instances BUFFER_SIZE, // output buffer size BUFFER_SIZE, // input buffer size NMPWAIT_USE_DEFAULT_WAIT, // client time-out &sa); if (hPipe == INVALID_HANDLE_VALUE) HANDLE_START_ERROR("Initial CreateNamedPipe() failed"); CloseHandle(hPipe); } else // Shared memory is the ipcMethod { // To support Fast User Switching/Terminal Server need Global\\ // prepended for WinXP, Win2K and above. STAFString globalStr = ""; if (STAFUtilWin32GetWinType() & kSTAFWin2KPlus) globalStr = "Global\\"; STAFString sharedMemoryName = globalStr + provider->ipcName + "/SharedMemory"; provider->fileMap = 0; provider->sharedMem = 0; // Create events for server and client passing in security attributes provider->serverSynch = CreateEvent( &sa, TRUE, FALSE, STAFString(globalStr + provider->ipcName + "/ServerSynch"). toCurrentCodePage()->buffer()); provider->clientSynch = CreateEvent( &sa, TRUE, FALSE, STAFString(globalStr + provider->ipcName + "/ClientSynch"). toCurrentCodePage()->buffer()); // Obtain Shared Memory with security provider->fileMap = CreateFileMapping( INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, 2 * sizeof(DWORD) + 2 * sizeof(HANDLE), sharedMemoryName.toCurrentCodePage()->buffer()); if (provider->fileMap == 0) HANDLE_START_ERROR("CreateFileMapping()"); provider->sharedMem = MapViewOfFile( provider->fileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (provider->sharedMem == 0) HANDLE_START_ERROR("MapViewOfFile()"); DWORD *serverPID = (DWORD *)((char *)provider->sharedMem + sizeof(DWORD)); *serverPID = GetCurrentProcessId(); if (STAFUtilWin32GetWinType() & kSTAFWin2KPlus) { // Open the Process to get its handle to pass to SetSecurityInfo HANDLE pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, *serverPID); if (pHandle == 0) HANDLE_START_ERROR("OpenProcess()"); int rc = SetSecurityInfo( pHandle, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, 0, 0); if (rc != 0) HANDLE_START_ERROR2("SetSecurityInfo()", rc); } } if (sd != 0) STAFUtilWin32DeleteNullSD(&sd); // Ok, the provider is now ready provider->syncSem->reset(); provider->state = kSTAFConnectionProviderActive; provider->threadManager->dispatch(STAFLocalIPCRunThread, provider); provider->syncSem->wait(); return kSTAFOk; } CATCH_STANDARD("STAFConnectionProviderStart"); return kSTAFUnknownError;}STAFRC_t STAFConnectionProviderStop(STAFConnectionProvider_t baseProvider, void *stopInfo, unsigned int stopInfoLevel, STAFString_t *errorBuffer){ if (baseProvider == 0) return kSTAFInvalidObject; if (stopInfoLevel != 0) return kSTAFInvalidAPILevel; try { STAFLocalConnectionProviderImpl *provider = static_cast<STAFLocalConnectionProviderImpl *>(baseProvider); provider->state = kSTAFConnectionProviderStopped; // Wake up the run thread provider->syncSem->reset(); if (provider->ipcMethod == kSharedMemory) SetEvent(provider->serverSynch); if (provider->syncSem->wait(10000) != 0) { STAFTrace::trace( kSTAFTraceError, STAFString("STAFLocalIPCConnectionProviderStop - Timed out " "waiting for run thread to wake up")); } // Release resources acquired when starting provider if (provider->ipcMethod == kSharedMemory) { UnmapViewOfFile(provider->sharedMem); CloseHandle(provider->fileMap); CloseHandle(provider->clientSynch); CloseHandle(provider->serverSynch); } return kSTAFOk; } CATCH_STANDARD("STAFConnectionProviderStop"); return kSTAFUnknownError;}STAFRC_t STAFConnectionProviderDestruct(STAFConnectionProvider_t *baseProvider, void *destructInfo, unsigned int destructInfoLevel, STAFString_t *errorBuffer){ if (baseProvider == 0) return kSTAFInvalidObject; if (*baseProvider == 0) return kSTAFInvalidObject; if (destructInfoLevel != 0) return kSTAFInvalidAPILevel; try { STAFLocalConnectionProviderImpl *provider = static_cast<STAFLocalConnectionProviderImpl *>(*baseProvider); STAFMutexSemLock lock(sActiveProvidersSem); sActiveProviders.erase(provider); if (provider->state != kSTAFConnectionProviderStopped) { provider->state = kSTAFConnectionProviderStopped; if (provider->ipcMethod == kSharedMemory) { UnmapViewOfFile(provider->sharedMem); CloseHandle(provider->fileMap); } } delete provider; provider = 0; return kSTAFOk; } CATCH_STANDARD("STAFConnectionProviderDestruct"); return kSTAFUnknownError;}STAFRC_t STAFConnectionProviderConnect(STAFConnectionProvider_t baseProvider, STAFConnection_t *connection, void *connectInfo, unsigned int connectInfoLevel, STAFString_t *errorBuffer){ if (baseProvider == 0) return kSTAFInvalidObject; if (connectInfoLevel != 1) return kSTAFInvalidAPILevel; if (connection == 0) return kSTAFInvalidParm; // XXX: Need to read connectInfoLevel and take appropriate action try { STAFLocalConnectionProviderImpl *provider = static_cast<STAFLocalConnectionProviderImpl *>(baseProvider); STAFLocalConnectionImpl connImpl; connImpl.ipcMethod = provider->ipcMethod; if (provider->ipcMethod == kNamedPipes) { STAFString pipeName = PIPENAME_PREFIX + provider->ipcName; unsigned int maxConnectAttempts = 20; // Try to connect to the server named pipe; wait and retry up to // the maxConnectAttempts, if necessary. for (unsigned int connectAttempt = 1; connectAttempt <= maxConnectAttempts; ++connectAttempt) { WaitNamedPipe(pipeName.toCurrentCodePage()->buffer(), 5000); connImpl.pipeHandle = CreateFile( pipeName.toCurrentCodePage()->buffer(), // pipe name GENERIC_READ | GENERIC_WRITE, // read and write access 0, // no sharing NULL, // default security attributes OPEN_EXISTING, // opens existing pipe 0, // default attributes NULL); // no template file // Break if the pipe handle is valid. if (connImpl.pipeHandle != INVALID_HANDLE_VALUE) break; unsigned int osRC = GetLastError(); if (osRC != ERROR_PIPE_BUSY) { STAFString connectError= STAFString( "Could not connect to the server named pipe: ") + osRC; if (errorBuffer) *errorBuffer = connectError.adoptImpl(); return kSTAFBaseOSError; } else if (connectAttempt == maxConnectAttempts) { STAFString connectError = STAFString( "Failed to connect to the server named pipe: ") + osRC; if (errorBuffer) *errorBuffer = connectError.adoptImpl(); return kSTAFBaseOSError; } } } else { // provider->ipcMethod is kSharedMemory PipeData pipeData = { 0 }; { STAFMutexSemLock lock(sPipeMapSem); GetPipeData(provider->ipcName, pipeData, errorBuffer); if (errorBuffer && *errorBuffer != 0) return kSTAFCommunicationError; } bool connected = ConnectToPipe(pipeData, connImpl.readHandle, connImpl.writeHandle, 0); if (!connected) { // This case means that the server we were attached to has // disappeared. So, let's flush the cache and try again. { STAFMutexSemLock lock(sPipeMapSem); sPipeMap.erase(provider->ipcName); GetPipeData(provider->ipcName, pipeData, errorBuffer); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -