////////////////////////////////////////////////////////////////////////// // // NdasDiStopService // ////////////////////////////////////////////////////////////////////////// NDASDI_API BOOL WINAPI NdasDiStopServiceSCH( IN SC_HANDLE schSCManager, IN LPCTSTR ServiceName) { BOOL fSuccess = FALSE; DPInfo(_FT("Stopping a service %s.\n"), ServiceName); AutoSCHandle hService = OpenService( schSCManager, ServiceName, SERVICE_STOP); if (NULL == (SC_HANDLE) hService) { DPErrorEx(_FT("Opening a service %s failed: ")); return FALSE; } SERVICE_STATUS Status = {0}; fSuccess = ControlService(hService, SERVICE_CONTROL_STOP, &Status); if (!fSuccess) { DPErrorEx(_FT("Stopping a service %s failed: ")); return FALSE; } DPInfo(_FT("Service %s stopped successfully.\n")); return TRUE; }
BOOL CNdasEventMonitor::Initialize() { // // Initialize routine is reentrant one. // // // Auto-reset waitable timer // if (INVALID_HANDLE_VALUE == m_hHeartbeatMonitorTimer) { m_hHeartbeatMonitorTimer = ::CreateWaitableTimer(NULL, FALSE, NULL); } if (INVALID_HANDLE_VALUE == m_hHeartbeatMonitorTimer) { DPErrorEx(_FT("Timer creation failed: ")); return FALSE; } if (NULL == m_hLogDeviceSetChangeEvent) { m_hLogDeviceSetChangeEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); } if (NULL == m_hLogDeviceSetChangeEvent) { DPErrorEx(_FT("Logical device set change event creation failed: ")); return FALSE; } return CTask::Initialize(); }
static LPTSTR pQuotePath(IN LPCTSTR szPath) { #ifdef UNICODE static const DWORD PATH_LIMIT = 32767; #else static const DWORD PATH_LIMIT = MAX_PATH; #endif size_t cch = 0; HRESULT hr = StringCchLength(szPath, PATH_LIMIT, &cch); _ASSERTE(SUCCEEDED(hr)); if (FAILED(hr)) { DPErrorEx(_FT("Get string length for %s failed (hr = %08X): "), hr); return NULL; } // do not quote for already quoted path LPTSTR szQuoted = (LPTSTR) LocalAlloc(LPTR, (cch + 2) * sizeof(TCHAR)); hr = StringCchPrintf(szQuoted, cch + 2, _T("\"%s\""), szPath); _ASSERTE(SUCCEEDED(hr)); if (FAILED(hr)) { DPErrorEx(_FT("Quoting a string %s failed (hr = 0x%08X): "), szPath, hr); LocalFree((HLOCAL)szQuoted); return NULL; } return szQuoted; }
NDASDI_API BOOL WINAPI NdasDiStartServiceSCH( IN SC_HANDLE schSCManager, IN LPCTSTR ServiceName, IN DWORD argc, IN LPCTSTR* argv) { BOOL fSuccess = FALSE; DPInfo(_FT("Starting a service %s.\n"), ServiceName); AutoSCHandle hService = OpenService( schSCManager, ServiceName, SERVICE_STOP); if (NULL == (SC_HANDLE) hService) { DPErrorEx(_FT("Opening a service %s failed: ")); return FALSE; } fSuccess = StartService(hService, argc, argv); if (!fSuccess) { DPErrorEx(_FT("Starting a service %s failed: ")); return FALSE; } DPInfo(_FT("Service %s started successfully.\n")); return TRUE; }
BOOL CNdasEventPublisher::AcceptNewConnection() { CLIENT_DATA* pClientData = NULL; pClientData = new CLIENT_DATA; ::ZeroMemory(pClientData, sizeof(CLIENT_DATA)); if (NULL == pClientData) { DPErrorEx(_FT("Out of memory: ")); return FALSE; } pClientData->overlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); if (NULL == pClientData->overlapped.hEvent) { // Unable to create an event DPErrorEx(_FT("Creating an event failed: ")); delete pClientData; return FALSE; } pClientData->hPipe = CreatePipeInstance(&pClientData->overlapped); if (INVALID_HANDLE_VALUE == pClientData->hPipe) { // Unable to create a pipe instance DPErrorEx(_FT("Creating the pipe instance failed: ")); ::CloseHandle(pClientData->overlapped.hEvent); pClientData->overlapped.hEvent = NULL; delete pClientData; return FALSE; } m_PipeData.push_back(pClientData); return TRUE; }
NDASUSER_LINKAGE HNDASEVENTCALLBACK NDASUSERAPI NdasRegisterEventCallback( NDASEVENTPROC lpEventProc, LPVOID lpContext) { if (IsBadCodePtr(reinterpret_cast<FARPROC>(lpEventProc))) { ::SetLastError(NDASUSER_ERROR_INVALID_PARAMETER); return FALSE; } BOOL fSuccess = _pEventSubscriber->Initialize(); if (!fSuccess) { DPErrorEx(_FT("Event Subscriber initialization failed: ")); return FALSE; } HNDASEVENTCALLBACK hCallback = _pEventSubscriber->AddCallback(lpEventProc, lpContext); if (NULL == hCallback) { DPErrorEx(_FT("Adding callback function failed: ")); return FALSE; } return hCallback; }
BOOL WINAPI NdasDmGetVolumeNumberOfDriveLetter(int drvno, ULONG *vol) { BOOL bret = FALSE ; HANDLE volMgr ; TCHAR volName[] = _T("\\\\.\\A:") ; VOLUME_NUMBER VN ; ULONG retsz ; // // fix volume name // volName[4] += (TCHAR)drvno ; DPInfo(_FT("DOS device name: %s\n"), volName); // // open the volume manager // volMgr = CreateFile(volName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL) ; if(volMgr == INVALID_HANDLE_VALUE) { DPErrorEx(_FT("CreateFile(%s) failed: "), volName); return FALSE ; } bret = DeviceIoControl( volMgr, IOCTL_VOLUME_QUERY_VOLUME_NUMBER, NULL, // lpInBuffer 0, // size of input buffer (LPVOID) &VN, // output buffer (DWORD) sizeof(VN), // size of output buffer &retsz, // number of bytes returned NULL // OVERLAPPED structure ) ; if(bret == FALSE) { DPErrorEx(_FT("DeviceIoControl(IOCTL_VOLUME_QUERY_VOLUME_NUMBER) failed: ")); goto cleanup ; } DPInfo(_FT("Volume Number:%d\n"), VN.VolumeNumber ); DPInfo(_FT("Volume Manager Name:%ws\n"), VN.VolumeManagerName ); *vol = VN.VolumeNumber ; cleanup: if(volMgr != 0 && volMgr != INVALID_HANDLE_VALUE) CloseHandle(volMgr) ; return bret ; }
NDASDI_API BOOL WINAPI NdasDiFindService( LPCTSTR ServiceName, LPBOOL pbPendingDeletion) { BOOL fSuccess = FALSE; DPInfo(_FT("Finding a service %s.\n"), ServiceName); AutoSCHandle schSCManager = OpenSCManager( NULL, NULL, GENERIC_EXECUTE); if (NULL == (SC_HANDLE) schSCManager) { DPErrorEx(_FT("Opening SC Manager failed: ")); return FALSE; } fSuccess = NdasDiServiceExistsSCH(schSCManager, ServiceName); if (fSuccess) { DPInfo(_FT("Service %s exists.\n"), ServiceName); fSuccess = NdasDiIsServiceMarkedForDeletion(ServiceName); if (fSuccess) { *pbPendingDeletion = TRUE; } else { *pbPendingDeletion = FALSE; } return TRUE; } else { DPErrorEx(_FT("Failed:")); fSuccess = NdasDiIsServiceMarkedForDeletion(ServiceName); if (fSuccess) { *pbPendingDeletion = TRUE; return TRUE; } else { *pbPendingDeletion = FALSE; return FALSE; } } }
HANDLE CNdasEventSubscriber:: WaitServer(BOOL& bStopThread) { OVERLAPPED ov = {0}; ov.hEvent = m_hDataEvent; HANDLE hPipe = CreatePipeConnection(&ov); if (INVALID_HANDLE_VALUE == hPipe) { NDAS_EVENT_INFO ei = {0}; ei.EventType = NDAS_EVENT_TYPE_CONNECTION_FAILED; CallEventProc(::GetLastError(), NULL); } // // Wait for 5 seconds and try again // while (INVALID_HANDLE_VALUE == hPipe) { { NDAS_EVENT_INFO ei = {0}; ei.EventType = NDAS_EVENT_TYPE_CONNECTION_FAILED; CallEventProc(::GetLastError(), &ei); } DWORD dwWaitResult = ::WaitForSingleObject( m_hThreadStopEvent, 5 * 1000); if (WAIT_OBJECT_0 == dwWaitResult) { bStopThread = TRUE; return INVALID_HANDLE_VALUE; } else if (WAIT_TIMEOUT == dwWaitResult) { { NDAS_EVENT_INFO ei = {0}; ei.EventType = NDAS_EVENT_TYPE_RETRYING_CONNECTION; CallEventProc(::GetLastError(), &ei); } hPipe = CreatePipeConnection(&ov); } else { DPErrorEx(_FT("Wait failed: \n")); return INVALID_HANDLE_VALUE; } } { NDAS_EVENT_INFO ei = {0}; ei.EventType = NDAS_EVENT_TYPE_CONNECTED; CallEventProc(0, &ei); } return hPipe; }
BOOL GetLocalLpxAddressList( IN SOCKET s, IN DWORD cbBuffer, OUT LPSOCKET_ADDRESS_LIST lpBuffer, OUT LPDWORD pcbBytesReturned) { _ASSERTE(INVALID_SOCKET != s); _ASSERTE(!IsBadWritePtr(lpBuffer, cbBuffer)); INT iError = WSAIoctl( s, SIO_ADDRESS_LIST_QUERY, NULL, 0, lpBuffer, cbBuffer, pcbBytesReturned, NULL, NULL); if (iError != 0) { DPErrorEx(_FT("SIO_ADDRESS_LIST_QUERY failed: ")); return FALSE; } return TRUE; }
BOOL CNdasUnitDevice::GetHostUsageCount( LPDWORD lpnROHosts, LPDWORD lpnRWHosts, BOOL fUpdate) { ximeta::CAutoLock autolock(this); _ASSERTE(!IsBadWritePtr(lpnROHosts, sizeof(DWORD))); _ASSERTE(!IsBadWritePtr(lpnRWHosts, sizeof(DWORD))); if (fUpdate) { BOOL fSuccess = m_pParentDevice->UpdateDeviceInfo(); if (!fSuccess) { DPErrorEx(_FT("Update device status failed: ")); return FALSE; } } *lpnROHosts = m_devInfo.dwROHosts; *lpnRWHosts = m_devInfo.dwRWHosts; DBGPRT_INFO(_FT("Host Usage Count: RO %d, RW %d.\n"), m_devInfo.dwROHosts, m_devInfo.dwRWHosts); return TRUE; }
NDASDI_API BOOL WINAPI NdasDiStartService( IN LPCTSTR ServiceName, IN DWORD argc, IN LPCTSTR* argv) { BOOL fSuccess = FALSE; AutoSCHandle schSCManager = OpenSCManager( NULL, NULL, GENERIC_EXECUTE); DPInfo(_FT("Starting a service %s.\n"), ServiceName); if (NULL == (SC_HANDLE) schSCManager) { DPErrorEx(_FT("Opening SC Manager failed: ")); return FALSE; } return NdasDiStartServiceSCH( schSCManager, ServiceName, argc, argv); }
BOOL CNdasEventPublisher::SendVersionInfo(HANDLE hPipe, LPOVERLAPPED lpOverlapped) { const DWORD cbMessage = sizeof(NDAS_EVENT_MESSAGE); NDAS_EVENT_MESSAGE msgVersion = {0}; msgVersion.MessageSize = cbMessage; msgVersion.EventType = NDAS_EVENT_TYPE_VERSION_INFO; msgVersion.VersionInfo.MajorVersion = NDAS_EVENT_VERSION_MAJOR; msgVersion.VersionInfo.MinorVersion = NDAS_EVENT_VERSION_MINOR; DWORD cbWritten(0); BOOL fSuccess = ::WriteFile( hPipe, &msgVersion, cbMessage, &cbWritten, lpOverlapped); if (!fSuccess && ERROR_IO_PENDING != ::GetLastError()) { DPErrorEx(_FT("Writing an initial version event failed: ")); return FALSE; } return TRUE; }
BOOL DisableDiskWriteCache(HANDLE hDisk) { BOOL fSuccess = FALSE; DWORD cbReturned = 0; DISK_CACHE_INFORMATION diskCacheInfo = {0}; fSuccess = ::DeviceIoControl( hDisk, IOCTL_DISK_GET_CACHE_INFORMATION, NULL, 0, &diskCacheInfo, sizeof(DISK_CACHE_INFORMATION), &cbReturned, NULL); if (!fSuccess) { DPErrorEx(_FT("DeviceIoControl(IOCTL_DISK_GET_CACHE_INFORMATION) failed: ")); return FALSE; } DPInfo(_FT("Disk Write Cache Enabled: %d.\n"), diskCacheInfo.WriteCacheEnabled); if (!diskCacheInfo.WriteCacheEnabled) { DPInfo(_FT("Disk Write Cache Already Disabled. Ignoring.\n")); return TRUE; } diskCacheInfo.WriteCacheEnabled = FALSE; fSuccess = ::DeviceIoControl( hDisk, IOCTL_DISK_SET_CACHE_INFORMATION, &diskCacheInfo, sizeof(DISK_CACHE_INFORMATION), &diskCacheInfo, sizeof(DISK_CACHE_INFORMATION), &cbReturned, NULL); if (!fSuccess) { DPErrorEx(_FT("DeviceIoControl(IOCTL_DISK_SET_CACHE_INFORMATION) failed: ")); return FALSE; } DPInfo(_FT("Disable Write Cache (%p) completed successfully.\n"), hDisk); return TRUE; }
unsigned int _stdcall DebugWndThreadProc(void * pArg) { // // A hidden window for device notification // (Message-only windows cannot receive WM_BROADCAST) // WNDCLASSEX wcex; ::ZeroMemory(&wcex, sizeof(WNDCLASSEX)); wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = 0; wcex.lpfnWndProc = (WNDPROC)DebugWndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = NULL; wcex.hIcon = NULL; wcex.hCursor = NULL; wcex.hbrBackground = NULL; wcex.lpszMenuName = NULL; wcex.lpszClassName = TEXT("NDASHelperServiceWnd"); wcex.hIconSm = NULL; ::RegisterClassEx(&wcex); HWND* phWnd = (HWND*) pArg; *phWnd = ::CreateWindowEx( WS_EX_OVERLAPPEDWINDOW, TEXT("NDASHelperServiceWnd"), TEXT("NDAS Helper Service"), WS_EX_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, NULL, NULL, NULL); if (*phWnd == NULL) { DPErrorEx(TEXT("Creating Debug Window failed.\n")); _ASSERT(FALSE && "Creating Debug Window failed.\n"); }; // ::ShowWindow(*phWnd, SW_SHOW); MSG msg; while (::GetMessage(&msg, NULL, 0, 0)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } _endthreadex(0); return 0; }
BOOL WINAPI NdasDmGetScsiPortNumberOfDisk( IN DWORD dwPhysicalDiskNumber, OUT LPDWORD lpdwScsiPortNumber) { _ASSERTE(!IsBadWritePtr(lpdwScsiPortNumber, sizeof(DWORD))); // // make up Physical Drive Name // TCHAR szDiskDevicePath[_MAX_PATH + 1]; HRESULT hr = ::StringCchPrintf( szDiskDevicePath, _MAX_PATH + 1, _T("\\\\.\\PHYSICALDRIVE%d"), dwPhysicalDiskNumber); _ASSERT(SUCCEEDED(hr)); DPInfo(_FT("Disk Device Path:%s\n"), szDiskDevicePath); // // open the disk device // DPTrace(_FT("CreateFile(%s)\n"), szDiskDevicePath); HANDLE hDisk = ::CreateFile( szDiskDevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hDisk) { DPErrorEx(_FT("CreateFile(%s) failed: "), szDiskDevicePath); return FALSE; } // // Get SCSI Port Number of the Disk // BOOL fSuccess = NdasDmGetScsiPortNumberOfDisk(hDisk, lpdwScsiPortNumber); if (!fSuccess) { DPError(_FT("NdasDmGetScsiPortNumberOfDisk(%s) failed.\n"), szDiskDevicePath); (VOID) ::CloseHandle(hDisk); return FALSE; } (VOID) ::CloseHandle(hDisk); return TRUE; }
NDASDI_API BOOL WINAPI NdasDiDeleteServiceSCH( IN SC_HANDLE schSCManager, IN LPCTSTR ServiceName) { BOOL fSuccess = FALSE; DPInfo(_FT("Deleting Service %s.\n"), ServiceName); AutoSCLock scLock = LockServiceDatabase(schSCManager); if (NULL == (SC_LOCK) scLock) { DPErrorEx(_FT("Locking service database failed: ")); return FALSE; } AutoSCHandle hService = OpenService( schSCManager, ServiceName, DELETE); if (NULL == (SC_HANDLE) hService) { DPErrorEx(_FT("Opening a service %s failed: "), ServiceName); return FALSE; } fSuccess = DeleteService(hService); if (!fSuccess) { DPErrorEx(_FT("Deleting a service %s failed: "), ServiceName); return FALSE; } DPInfo(_FT("Service %s deleted successfully.\n"), ServiceName); return TRUE; }
BOOL CService:: ReportStatusToSCMgr( DWORD dwCurrentState, DWORD dwWaitHint /* = 3000 */, DWORD dwWin32ExitCode /* = NO_ERROR */) { static DWORD dwCheckPoint = 1; BOOL fSuccess= TRUE; if (m_bDebugMode) { // when debugging we don't report to the SCM return fSuccess; } if (dwCurrentState == SERVICE_START_PENDING) { m_ssStatus.dwControlsAccepted = 0; } else { m_ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT; } m_ssStatus.dwCurrentState = dwCurrentState; m_ssStatus.dwWin32ExitCode = dwWin32ExitCode; m_ssStatus.dwWaitHint = dwWaitHint; if ( ( dwCurrentState == SERVICE_RUNNING ) || ( dwCurrentState == SERVICE_STOPPED ) ) { m_ssStatus.dwCheckPoint = 0; } else { m_ssStatus.dwCheckPoint = static_cast<DWORD>( InterlockedIncrement(reinterpret_cast<LPLONG>(&dwCheckPoint))); } // // Report the status of the service to the service control manager. // fSuccess = ::SetServiceStatus( m_sshStatusHandle, &m_ssStatus); if (!fSuccess) { DPErrorEx(_FT("Setting Service Status to %d failed:"), m_ssStatus); // ReportEventError(TEXT("SetServiceStatus")); } return fSuccess; }
BOOL CNdasDeviceComm::Initialize(BOOL bWriteAccess) { m_bWriteAccess = bWriteAccess; InitializeLANSCSIPath(); LPX_ADDRESS local, remote; local = m_pDevice->GetLocalLpxAddress(); remote = m_pDevice->GetRemoteLpxAddress(); SOCKET sock = CreateLpxConnection(&remote, &local); if (INVALID_SOCKET == sock) { DPErrorEx(_FT("CreateLpxConnection failed: ")); return FALSE; } m_lspath.HWType = m_pDevice->GetHWType(); m_lspath.HWVersion = m_pDevice->GetHWVersion(); m_lspath.connsock = sock; INT iResult = Login(&m_lspath, LOGIN_TYPE_NORMAL); if (0 != iResult) { // TODO: LANDISK_ERROR_BADKEY? DPErrorEx(_FT("Login failed (ret %d): "), iResult); ::closesocket(sock); return FALSE; } m_bInitialized = TRUE; return TRUE; }
DWORD CNdasIXBcast::OnTaskStart() { if (0 == m_NDFSVersion.wMajor && 0 == m_NDFSVersion.wMinor) { return 0; } HANDLE hEvents[2]; hEvents[0] = m_hTaskTerminateEvent; hEvents[1] = m_sockAddrChangeNotifier.GetChangeEvent(); // CTask::Initialized called? _ASSERTE(NULL != hEvents[0]); // m_sockAddrChangeNotifier is initialized? _ASSERTE(NULL != hEvents[1]); // // Initial bind // ResetBind(); // // initial LPX socket address list is attained // DWORD dwTimeout = 1000; // broadcast interval while (1) { DWORD dwWaitResult = ::WaitForMultipleObjects( 2, hEvents, FALSE, dwTimeout); if (WAIT_OBJECT_0 == dwWaitResult) { return 0; } else if (WAIT_OBJECT_0 + 1 == dwWaitResult) { // reset bind ResetBind(); } else if (WAIT_TIMEOUT == dwWaitResult) { BroadcastStatus(); } else { DPErrorEx(_FT("Unexpected wait result %d: "), dwWaitResult); _ASSERTE(FALSE); } } }
BOOL CNdasUnitDiskDevice::IsBitmapClean() { ximeta::CAutoLock autolock(this); CNdasDeviceComm devComm(*m_pParentDevice, m_unitDeviceId.UnitNo); BOOL fSuccess = devComm.Initialize(FALSE); if(!fSuccess) { return FALSE; } NDAS_UNITDEVICE_INFORMATION unitDevInfo; fSuccess = devComm.GetUnitDeviceInformation(&unitDevInfo); if (!fSuccess) { DPErrorEx(_FT("GetUnitDeviceInformation of %s failed: "), this->ToString()); return FALSE; } BYTE BitmapData[128 * 512] = {0}; // 1MB from NDAS_BLOCK_LOCATION_BITMAP for(INT i = 0; i < 16; i++) { fSuccess = devComm.ReadDiskBlock(BitmapData, NDAS_BLOCK_LOCATION_BITMAP + (i * 128), 128); if(!fSuccess) { return FALSE; } INT j = 0; PULONG pBitmapData = (PULONG)BitmapData; for(; j < 128 * 512 / 4; ++j) { if(*pBitmapData) { return FALSE; } pBitmapData++; } } return TRUE; }
NDASDI_API BOOL WINAPI NdasDiDeleteService( IN LPCTSTR ServiceName) { AutoSCHandle schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); DPInfo(_FT("Deleting Service %s.\n"), ServiceName); if (NULL == (SC_HANDLE) schSCManager) { DPErrorEx(_FT("Opening SC Manager failed: ")); return FALSE; } return NdasDiDeleteServiceSCH(schSCManager, ServiceName); }
BOOL DisableDiskWriteCache(LPCTSTR szDiskPath) { DPInfo(_FT("CreateFile(%s).\n"), szDiskPath); AutoFileHandle hDisk = ::CreateFile( szDiskPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == hDisk) { DPErrorEx(_FT("CreateFile(%s) failed: "), szDiskPath); return FALSE; } return DisableDiskWriteCache(hDisk); }
BOOL GetLocalLpxAddressList( IN DWORD cbBuffer, OUT LPSOCKET_ADDRESS_LIST lpBuffer, OUT LPDWORD pcbBytesReturned) { SOCKET sock = ::WSASocket( AF_LPX, SOCK_STREAM, IPPROTO_LPXTCP, NULL, 0, 0); if (INVALID_SOCKET == sock) { DPErrorEx(_FT("Socket creation failed: ")); return FALSE; } BOOL fSuccess = GetLocalLpxAddressList( sock, cbBuffer, lpBuffer, pcbBytesReturned); // // Close socket may shadow last error // int iWSALastError = ::WSAGetLastError(); INT iResult = ::closesocket(sock); if (0 != iResult) { DPWarningEx(_FT("Closing a socket failed: ")); } ::WSASetLastError(iWSALastError); return fSuccess; }
BOOL CNamedPipeTransport:: Accept( LPOVERLAPPED lpOverlapped) { _ASSERTE( (NULL == lpOverlapped) || (!IsBadReadPtr(lpOverlapped, sizeof(LPOVERLAPPED)) && NULL != lpOverlapped->hEvent && INVALID_HANDLE_VALUE != lpOverlapped->hEvent)); BOOL fConnected = ::ConnectNamedPipe(m_hPipe, lpOverlapped); if (fConnected) { DPInfo(_FT("Accepting a new connection.\n")); return TRUE; } if (lpOverlapped) { // if overlapped operation ConnectNamedPipe should return FALSE; DWORD dwError = ::GetLastError(); switch (dwError) { case ERROR_PIPE_CONNECTED: ::SetEvent(lpOverlapped->hEvent); // omitting break is intentional case ERROR_IO_PENDING: DPInfo(_FT("Accepting a new connection.\n")); return TRUE; default: // An error occurs during the connect operation DPErrorEx(_FT("ConnectNamedPipe failed: ")); return FALSE; } } return FALSE; }
BOOL CTask:: Run() { _ASSERTE(m_bRunnable && "Have you ever called CTask::Initialize()?"); if (FALSE == m_bRunnable) { return FALSE; } #if USE_WINAPI_THREAD m_hTaskThreadHandle = ::CreateThread( NULL, 0, TaskThreadProcKickStart, this, NULL, &m_dwTaskThreadId); #else m_hTaskThreadHandle = (HANDLE) _beginthreadex( NULL, 0, TaskThreadProcKickStart, this, NULL, (unsigned int*)&m_dwTaskThreadId); #endif if (NULL == m_hTaskThreadHandle) { // TODO: Event Log Error Here DPErrorEx(_T("Task thread creation failed!\n")); return FALSE; } m_bIsRunning = TRUE; return TRUE; }
DWORD CNdasEventMonitor::OnTaskStart() { BOOL bTerminateThread(FALSE); // 15 sec = 10,000,000 nanosec // negative value means relative time LARGE_INTEGER liDueTime; liDueTime.QuadPart = - 10 * 1000 * 1000; BOOL fSuccess = ::SetWaitableTimer( m_hHeartbeatMonitorTimer, &liDueTime, HEARTBEAT_MONITOR_INTERVAL, NULL, NULL, FALSE); if (!fSuccess) { DPErrorEx(_FT("Setting waitable timer failed: ")); } do { // // Lock against m_vLogDevice set change // this->Lock(); DWORD dwLogDevices = m_vLogDevices.size(); DWORD dwHandles = 3 + 2 * dwLogDevices; HANDLE* hWaitingHandles = new HANDLE[dwHandles]; hWaitingHandles[0] = m_hTaskTerminateEvent; hWaitingHandles[1] = m_hLogDeviceSetChangeEvent; hWaitingHandles[2] = m_hHeartbeatMonitorTimer; PCNdasLogicalDeviceVector::const_iterator itr = m_vLogDevices.begin(); for (DWORD i = 3; itr != m_vLogDevices.end(); ++itr, ++i) { PCNdasLogicalDevice pLogDevice = *itr; hWaitingHandles[i] = pLogDevice->GetDisconnectEvent(); hWaitingHandles[dwLogDevices + i] = pLogDevice->GetAlarmEvent(); } this->Unlock(); fSuccess = ::ResetEvent(m_hLogDeviceSetChangeEvent); _ASSERTE(fSuccess); BOOL bResetLogDeviceSet(FALSE); do { DWORD dwWaitResult = ::WaitForMultipleObjects( dwHandles, hWaitingHandles, FALSE, INFINITE); if (WAIT_OBJECT_0 == dwWaitResult) { // // Terminate Thread Event // bTerminateThread = TRUE; } else if (WAIT_OBJECT_0 + 1 == dwWaitResult) { // // LogicalDeviceSetChange Event // bResetLogDeviceSet = TRUE; } else if (WAIT_OBJECT_0 + 2 == dwWaitResult) { ximeta::CAutoLock autolock(this); // // Heartbeat Monitor Timer Event // PCNdasDeviceSet::const_iterator devitr = m_hbMonDevices.begin(); m_bIterating = TRUE; for (; devitr != m_hbMonDevices.end();) { PCNdasDevice pDevice = *devitr; BOOL fDetach = pDevice->OnStatusCheck(); if (fDetach) { devitr = m_hbMonDevices.erase(devitr); pDevice->Release(); } else { ++devitr; } } m_bIterating = FALSE; // // Check the logical devices // std::for_each( m_vLogDevices.begin(), m_vLogDevices.end(), NdasLogicalDeviceStatusCheck); } else if (WAIT_OBJECT_0 + 3 <= dwWaitResult && dwWaitResult < WAIT_OBJECT_0 + 3 + dwLogDevices) { // // Disconnect Event // DWORD n = dwWaitResult - (WAIT_OBJECT_0 + 3); BOOL fHandled = OnLogicalDeviceDisconnected(n); if (!fHandled) { fSuccess = ::ResetEvent(hWaitingHandles[dwWaitResult - WAIT_OBJECT_0]); _ASSERTE(fSuccess); } } else if (WAIT_OBJECT_0 + 3 + dwLogDevices <= dwWaitResult && dwWaitResult < WAIT_OBJECT_0 + 3 + 2 * dwLogDevices) { // // Alarm Event // DWORD n = dwWaitResult - (WAIT_OBJECT_0 + 3 + dwLogDevices); BOOL fHandled = OnLogicalDeviceAlarmed(n); if (!fHandled) { fSuccess = ::ResetEvent(hWaitingHandles[dwWaitResult - WAIT_OBJECT_0]); _ASSERTE(fSuccess); } } else { // _ASSERTE(FALSE); // Some handles may be already invalid. // LogicalDeviceSetChange Event // bResetLogDeviceSet = TRUE; DPErrorEx(_FT("Wait failed: ")); } } while (!bResetLogDeviceSet && !bTerminateThread); delete [] hWaitingHandles; } while (!bTerminateThread); fSuccess = ::CancelWaitableTimer(m_hHeartbeatMonitorTimer); if (!fSuccess) { DPErrorEx(_FT("Canceling waitable timer failed: ")); } return 0; }
BOOL CNdasInstanceManager:: Initialize_() { BOOL fSuccess; if (NULL == m_pHBListener) { m_pHBListener = new CNdasDeviceHeartbeatListener(); if (NULL == m_pHBListener) { DPErrorEx(_FT("Creating an instance of Heartbeat Listener failed: ")); return FALSE; } } fSuccess = m_pHBListener->Initialize(); if (!fSuccess) { DPErrorEx(_FT("Initializing Heartbeat Listener failed: ")); return FALSE; } if (NULL == m_pRegistrar) { m_pRegistrar = new CNdasDeviceRegistrar(); if (NULL == m_pRegistrar) { DPErrorEx(_FT("Creating an instance of Device Registrar failed: ")); return FALSE; } } if (NULL == m_pLogDevMan) { m_pLogDevMan = new CNdasLogicalDeviceManager(m_pRegistrar); if (NULL == m_pLogDevMan) { DPErrorEx(_FT("Creating an instance of Logical Device Manager failed: ")); return FALSE; } } if (NULL == m_pCommandServer) { m_pCommandServer = new CNdasCommandServer(); if (NULL == m_pCommandServer) { DPErrorEx(_FT("Creating an instance of Command Server failed: ")); return FALSE; } } fSuccess = m_pCommandServer->Initialize(); if (!fSuccess) { DPErrorEx(_FT("Initializing Command Server failed: ")); return FALSE; } if (NULL == m_pEventMonitor) { m_pEventMonitor = new CNdasEventMonitor(); if (NULL == m_pEventMonitor) { DPErrorEx(_FT("Creating an instance of Event Monitor failed: ")); return FALSE; } } fSuccess = m_pEventMonitor->Initialize(); if (!fSuccess) { DPErrorEx(_FT("Initializing Event Monitor failed: ")); return FALSE; } if (NULL == m_pEventPublisher) { m_pEventPublisher = new CNdasEventPublisher(); if (NULL == m_pEventPublisher) { DPErrorEx(_FT("Creating an instance of Event Publisher failed: ")); return FALSE; } } fSuccess = m_pEventPublisher->Initialize(); if (!fSuccess) { DPErrorEx(_FT("Initializing Event Publisher failed: ")); return FALSE; } return TRUE; }
BOOL CNdasEventMonitor::OnLogicalDeviceAlarmed(DWORD nWaitIndex) { ximeta::CAutoLock autolock(this); PCNdasLogicalDevice pLogDevice = NULL; if (nWaitIndex < m_vLogDevices.size()) { pLogDevice = m_vLogDevices[nWaitIndex]; } else { _ASSERTE(FALSE); return FALSE; } if (NULL == pLogDevice) { _ASSERTE(FALSE); return FALSE; } CNdasScsiLocation ndasScsiLocation = pLogDevice->GetNdasScsiLocation(); DPInfo(_FT("Alarm Event from %s: %s\n"), ndasScsiLocation.ToString(), pLogDevice->ToString()); if (ndasScsiLocation.IsInvalid()) { DBGPRT_ERR(_FT("Invalid SCSI Location\n")); _ASSERTE(FALSE); return FALSE; } // // reset the event to prevent consecutive same event pulse // // should return TRUE BOOL fSuccess = ::ResetEvent(pLogDevice->GetAlarmEvent()); _ASSERTE(fSuccess); ULONG ulAdapterStatus; fSuccess = ::LsBusCtlQueryStatus( ndasScsiLocation.SlotNo, &ulAdapterStatus); if (!fSuccess) { DPErrorEx(_FT("Unable to get alarm status, Ignored: ")); return TRUE; } if(pLogDevice->GetAdapterStatus() != ulAdapterStatus) { pLogDevice->SetAdapterStatus(ulAdapterStatus); CNdasEventPublisher* pEventPublisher = pGetNdasEventPublisher(); (VOID) pEventPublisher->LogicalDeviceAlarmed(pLogDevice->GetLogicalDeviceId(), ulAdapterStatus); } if(ADAPTERINFO_ISSTATUSFLAG(ulAdapterStatus, ADAPTERINFO_STATUSFLAG_MEMBER_FAULT)) pLogDevice->SetAllUnitDevicesFault(); return TRUE; }
DWORD CNdasEventPublisher::OnTaskStart() { _ASSERTE(NULL != m_hSemQueue && "Don't forget to call initialize()."); // Queue Semaphore, Terminating Thread, Pipe Instances(MAX...) HANDLE hWaitHandles[2 + MAX_NDAS_EVENT_PIPE_INSTANCES]; hWaitHandles[0] = m_hTaskTerminateEvent; hWaitHandles[1] = m_hSemQueue; // // initial pipe instance // m_PipeData.clear(); BOOL fSuccess = AcceptNewConnection(); if (!fSuccess) { DPErrorEx(_T("Creating a first pipe instance failed: ")); return -1; } BOOL bTerminate(FALSE); while (FALSE == bTerminate) { DWORD dwWaitHandles = 2 + m_PipeData.size(); for (DWORD i = 0; i < m_PipeData.size(); ++i) { hWaitHandles[i + 2] = m_PipeData[i]->overlapped.hEvent; } DWORD dwWaitResult = ::WaitForMultipleObjects( dwWaitHandles, hWaitHandles, FALSE, m_dwPeriod); if (dwWaitResult == WAIT_OBJECT_0) { // // Terminate Thread // bTerminate = TRUE; } else if (dwWaitResult == WAIT_OBJECT_0 + 1) { // // Event Message is queued // while (TRUE) { m_queueLock.Lock(); bool bEmpty = m_EventMessageQueue.empty(); if (bEmpty) { m_queueLock.Unlock(); break; } NDAS_EVENT_MESSAGE message = m_EventMessageQueue.front(); m_EventMessageQueue.pop(); m_queueLock.Unlock(); Publish(&message); } } else if (dwWaitResult >= WAIT_OBJECT_0 + 2 && dwWaitResult < WAIT_OBJECT_0 + 2 + m_PipeData.size()) { DWORD dwPipe = dwWaitResult - WAIT_OBJECT_0 - 2; DPInfo(_FT("Event Client %d\n"), dwPipe); CLIENT_DATA* pCurClientData = m_PipeData[dwPipe]; DPInfo(_FT("Connected: %d\n"), pCurClientData->bConnected); fSuccess = ::ResetEvent(pCurClientData->overlapped.hEvent); _ASSERT(fSuccess); if (!pCurClientData->bConnected) { // // create another instance // fSuccess = AcceptNewConnection(); if (!fSuccess) { DPWarningEx(_FT("Creating another pipe instance failed: ")); DPWarning(_FT("No more event subscribers can be accepted.\n")); } // AcceptNewConnection will invalidate pCurClientData; pCurClientData = m_PipeData.at(dwPipe); // // Accepting connection // pCurClientData->bConnected = TRUE; fSuccess = ::ResetEvent(pCurClientData->overlapped.hEvent); _ASSERT(fSuccess); // // Send a version event for connected client // fSuccess = SendVersionInfo( pCurClientData->hPipe, &pCurClientData->overlapped); // // Any failure will disconnect the client // if (!fSuccess && ERROR_IO_PENDING != ::GetLastError()) { ClientDataVector::iterator itr = m_PipeData.begin(); CleanupConnection(pCurClientData); while (itr != m_PipeData.end()) { if ((CLIENT_DATA*)*itr == pCurClientData) { m_PipeData.erase(itr); break; } ++itr; } DPInfo(_FT("Accepted removed event subscriber.\n")); } else { DPInfo(_FT("Accepted new event subscriber.\n")); } } else { } // ignore other status } else if (WAIT_TIMEOUT == dwWaitResult) { NDAS_EVENT_MESSAGE msg = {0}; msg.EventType = NDAS_EVENT_TYPE_PERIODIC; Publish(&msg); } else { // // Error // } } // // TODO: Add cleanup // DWORD nPipeData = m_PipeData.size(); ClientDataVector::iterator itr = m_PipeData.begin(); while (itr != m_PipeData.end()) { CleanupConnection(*itr); ++itr; } m_PipeData.clear(); _tprintf(TEXT("Terminating Publisher Thread...\n")); return 0; }