Beispiel #1
0
BOOL
CNdasService::Impl::ServiceStart(DWORD dwArgc, LPTSTR* lpArgs)
{
	XTLVERIFY(ReportServiceStartPending(1000));
	m_hStopServiceEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
	if (m_hStopServiceEvent.IsInvalid())
	{
		return FALSE;
	}

	XTLVERIFY(ReportServiceStartPending(1000));
	m_hWorkItemSemaphore = ::CreateSemaphore(NULL, 0, MAX_WORK_ITEMS, NULL);
	if (m_hWorkItemSemaphore.IsInvalid())
	{
		return FALSE;
	}

	XTLVERIFY(ReportServiceStartPending(1000));
	m_hStartServiceEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
	if (m_hStartServiceEvent.IsInvalid())
	{
		return FALSE;
	}

	XTLVERIFY(ReportServiceStartPending(1000));
	// Create an initialization thread
	if (!CreateThread())
	{
		return FALSE;
	}

	XTLVERIFY(ReportServiceRunning());

	return TRUE;
}
HRESULT
CNdasLogicalUnitManager::Unregister(INdasUnit* pNdasUnit)
{
	XTLTRACE2(NDASSVC_NDASLOGDEVMANAGER, TRACE_LEVEL_INFORMATION, 
		"Unregistering NdasUnit=%p from LDM\n", pNdasUnit);

	if (NULL == pNdasUnit)
	{
		return E_POINTER;
	}

	CComPtr<INdasLogicalUnit> pNdasLogicalUnit;
	COMVERIFY(pNdasUnit->get_NdasLogicalUnit(&pNdasLogicalUnit));

	DWORD luseq;
	COMVERIFY(pNdasUnit->get_LogicalUnitSequence(&luseq));

	COMVERIFY(pNdasLogicalUnit->RemoveNdasUnitInstance(pNdasUnit));

	DWORD instanceCount;
	COMVERIFY(pNdasLogicalUnit->get_NdasUnitInstanceCount(&instanceCount));

	if (0 == instanceCount) 
	{
		NDAS_LOGICALDEVICE_ID logicalUnitId;
		COMVERIFY(pNdasLogicalUnit->get_Id(&logicalUnitId));

		NDAS_LOGICALDEVICE_GROUP logicalUnitDefinition;
		COMVERIFY(pNdasLogicalUnit->get_LogicalUnitDefinition(&logicalUnitDefinition));

		LockInstance();
		XTLVERIFY(1 == m_LogicalUnitDefinitionMap.erase(logicalUnitDefinition));
		XTLVERIFY(1 == m_LogicalUnitIdMap.erase(logicalUnitId));
		size_t count = m_NdasLogicalUnits.GetCount();
		for (size_t i = 0; i < count; ++i)
		{
			INdasLogicalUnit* p = m_NdasLogicalUnits.GetAt(i);
			if (p == pNdasLogicalUnit)
			{
				m_NdasLogicalUnits.RemoveAt(i);
				break;
			}
		}
		XTLVERIFY(pDeallocateID(logicalUnitId));
		UnlockInstance();
	}

	return S_OK;
}
Beispiel #3
0
HANDLE
__stdcall
pOpenStorageDeviceByNumber(
	DWORD StorageDeviceNumber,
	ACCESS_MASK DeviceFileAccessMask
){
	// Device Name Format: \\.\PhysicalDriveXX
	TCHAR deviceName[24];
	XTLVERIFY(SUCCEEDED(
		::StringCchPrintf(
			deviceName, RTL_NUMBER_OF(deviceName), 
			_T("\\\\.\\PhysicalDrive%d"), StorageDeviceNumber)));

	XTL::AutoFileHandle hDisk = ::CreateFile(
		deviceName, 
		DeviceFileAccessMask, 
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		NULL, 
		OPEN_EXISTING, 
		0, 
		NULL);
	if (hDisk.IsInvalid())
	{
		XTLTRACE2(NdasVolTrace, TRACE_LEVEL_ERROR,
			"CreateFile(%ls) failed.\n", deviceName);
		return INVALID_HANDLE_VALUE;
	}
	return hDisk.Detach();
}
void
CNdasEventMonitor::Detach(INdasLogicalUnit* pNdasLogicalUnit)
{
	XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_INFORMATION, 
		"Detaching logical unit %p from the monitor\n",
		pNdasLogicalUnit);

	// LOGICAL DEVICE WRITE LOCK REGION
	{
		XTL::CWriterLockHolder holder(m_NdasLogicalUnitDataLock);
		// CInterfaceArray
		size_t count = m_NdasLogicalUnits.GetCount();
		for (size_t index = 0; index < count; ++index)
		{
			INdasLogicalUnit* p = m_NdasLogicalUnits.GetAt(index);
			if (pNdasLogicalUnit == p)
			{
				m_NdasLogicalUnits.RemoveAt(index);
				break;
			}
		}
	}
	// LOGICAL DEVICE WRITE LOCK REGION

	XTLVERIFY( ::SetEvent(m_NdasLogicalUnitSetChanged) );
}
CNdasDeviceComm::~CNdasDeviceComm()
{
	if (m_hNdas)
	{
		XTLVERIFY(SUCCEEDED(Disconnect()));
	}
}
DWORD 
CNdasCommandServer::CommandProcessStart(HANDLE hStopEvent)
{
	// 'Param' should be a copy of the 'Param' supplied by the caller
	// If the initiating thread has been abandoned already, Param will
	// be invalidated if it is an automatic object.

	// increment the work item count or 
	// check if stop event is signaled already
	HANDLE waitHandles[] = {hStopEvent, m_hProcSemaphore};
	const DWORD nWaitHandles = RTL_NUMBER_OF(waitHandles);

	DWORD waitResult = ::WaitForMultipleObjects(nWaitHandles, waitHandles, FALSE, INFINITE);
	if (WAIT_OBJECT_0 == waitResult)
	{
		return 0xFFFFFFFF; // stopped without actually starting a work
	}
	else if (WAIT_OBJECT_0 + 1 == waitResult)
	{
		// incremented work item count
		// execute the actual work item
		DWORD ret = ServiceCommand(hStopEvent);
		// decrement the work item count
		XTLVERIFY( ::ReleaseSemaphore(m_hProcSemaphore, 1, NULL) );
		return ret;
	}
	else
	{
		XTLASSERT(FALSE);
		return 0x0000FFFF;
	}
}
Beispiel #7
0
BOOL GetLocalLpxAddressList(
	IN DWORD cbBuffer,
	OUT LPSOCKET_ADDRESS_LIST lpBuffer,
	OUT LPDWORD pcbBytesReturned)
{
	SOCKET sock = ::WSASocket(
		AF_LPX, 
		SOCK_STREAM, 
		LPXPROTO_TCP,
		NULL,
		0,
		0);

	if (INVALID_SOCKET == sock) 
	{
		XTLTRACE2(NDASSVC_LPXCOMM, TRACE_LEVEL_ERROR,
			"WSASocket() failed, error=0x%X\n", GetLastError());
		return FALSE;
	}

	BOOL fSuccess = GetLocalLpxAddressList(
		sock, 
		cbBuffer,
		lpBuffer, 
		pcbBytesReturned);

	//
	// Close socket may shadow last error
	//
	XTL_SAVE_LAST_ERROR();

	XTLVERIFY(SOCKET_ERROR != closesocket(sock));

	return fSuccess;
}
Beispiel #8
0
void 
CNdasService::DestroyInstance(CNdasService* pService)
{
	delete pService;
	CNdasService::instance = NULL;
	XTLVERIFY(SOCKET_ERROR != WSACleanup());
}
Beispiel #9
0
CNdasService* 
CNdasService::CreateInstance()
{
	WSADATA wsaData;
	XTLVERIFY(SOCKET_ERROR != WSAStartup(MAKEWORD(2,2),&wsaData) );
	XTLASSERT(NULL == CNdasService::instance);
	CNdasService::instance = new CNdasService();
	return CNdasService::instance;
}
Beispiel #10
0
DWORD
CNdasService::Impl::OnServiceShutdown()
{
	XTLTRACE("System is shutting down...\n");

	m_cLogDeviceManager.OnShutdown();
	m_cDeviceEventHandler.OnShutdown();
	
	XTLVERIFY( ::LfsFiltCtlShutdown() );
	
	return NO_ERROR;
}
Beispiel #11
0
CNdasUnitDiskDevice::~CNdasUnitDiskDevice()
{
	XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_VERBOSE, 
		"%s\n", ToStringA());

	if (NULL != m_pAddTargetInfo) 
	{
		XTLVERIFY( HeapFree(::GetProcessHeap(), 0, m_pAddTargetInfo) );
		m_pAddTargetInfo = NULL;
	}
	if (NULL != m_pDIBv2) 
	{
		XTLVERIFY( HeapFree(::GetProcessHeap(), 0, m_pDIBv2) );
		m_pDIBv2  = NULL;
	}
	if (NULL != m_pBACL) 
	{
		XTLVERIFY( HeapFree(::GetProcessHeap(), 0, m_pBACL) );
		m_pBACL  = NULL;
	}
}
Beispiel #12
0
bool 
CNdasEventPreSubscriber::EndWaitForConnection()
{
	DWORD cbTransferred;
	BOOL fSuccess = ::GetOverlappedResult(m_hPipe, &m_overlapped,&cbTransferred,FALSE);
	if (!fSuccess)
	{
		XTLASSERT(ERROR_IO_INCOMPLETE == ::GetLastError());
		XTLVERIFY( ::CancelIo(m_hPipe) );
	}
	return fSuccess ? true : false;
}
Beispiel #13
0
DWORD
CNdasService::Impl::OnServiceShutdown()
{
	XTLTRACE2(NDASSVC_INIT, TRACE_LEVEL_INFORMATION, 
		"System is shutting down...\n");

	m_cLogDeviceManager.OnShutdown();
	m_cDeviceEventHandler.OnShutdown();

	XTLVERIFY( ::LfsFiltCtlShutdown() );
	
	return NO_ERROR;
}
Beispiel #14
0
HRESULT
pGetNdasSlotNumberFromDiskNumber(
	__in DWORD DiskNumber,
	__out LPDWORD NdasSlotNumber)
{
	WCHAR diskName[MAX_PATH];

	XTLVERIFY(SUCCEEDED(
		StringCchPrintfW(
			diskName, MAX_PATH,
			L"\\\\.\\PhysicalDrive%d", DiskNumber)));

	XTLTRACE2(NdasVolTrace, 2, "Disk Name: %ls\n", diskName);

	return pGetNdasSlotNumberFromDeviceNameW(diskName, NdasSlotNumber);
}
void
CNdasEventMonitor::Attach(INdasLogicalUnit* pNdasLogicalUnit)
{
	XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_INFORMATION,
		"Attaching logical unit %p to the monitor\n",
		pNdasLogicalUnit);

	// LOGICAL DEVICE WRITE LOCK REGION
	{
		XTL::CWriterLockHolder holder(m_NdasLogicalUnitDataLock);
		m_NdasLogicalUnits.Add(pNdasLogicalUnit);
	}
	// LOGICAL DEVICE WRITE LOCK REGION

	XTLVERIFY( ::SetEvent(m_NdasLogicalUnitSetChanged) );
}
Beispiel #16
0
HRESULT
pGetNdasSlotNumberForScsiPortNumber(
	__in DWORD ScsiPortNumber,
	__out LPDWORD NdasSlotNumber)
{
	//
	// Make up SCSI Port Name
	//
	
	WCHAR scsiPortName[MAX_PATH];

	XTLVERIFY(SUCCEEDED(
		StringCchPrintfW(
			scsiPortName, MAX_PATH,
			L"\\\\.\\Scsi%d:", ScsiPortNumber)));

	XTLTRACE2(NdasVolTrace, 2, "SCSI Port Name: %ls\n", scsiPortName);

	return pGetNdasSlotNumberFromDeviceNameW(scsiPortName, NdasSlotNumber);
}
Beispiel #17
0
HRESULT 
CNdasServiceDeviceEventHandler::RegisterDeviceInterfaceNotification(
	__in LPCGUID InterfaceGuid,
	__in LPCSTR TypeName)
{
	HDEVNOTIFY devNotifyHandle;

	HRESULT hr = pRegisterDeviceInterfaceNotification(
		m_hRecipient, 
		m_dwReceptionFlags,
		InterfaceGuid,
		&devNotifyHandle);

	if (FAILED(hr))
	{
		XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_ERROR,
			"RegisterDeviceInterfaceNotification failed, type=%hs, hr=0x%X\n",
			TypeName, hr);
		return hr;
	}

	try
	{
		m_DeviceInterfaceNotifyHandles.push_back(devNotifyHandle);
	}
	catch (...)
	{
		XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_ERROR,
			"RegisterDeviceInterfaceNotification failed, "
			"C++ exception, type=%hs\n",
			TypeName);			

		XTLVERIFY(UnregisterDeviceNotification(devNotifyHandle));

		return E_FAIL;
	}

	return S_OK;
}
Beispiel #18
0
HRESULT 
CNdasServiceDeviceEventHandler::UnregisterDeviceHandleNotification(
	__in HDEVNOTIFY DevNotifyHandle)
{
	EnterCriticalSection(&m_DevNotifyMapSection);

	DevNotifyMap::iterator itr = m_DevNotifyMap.find(DevNotifyHandle);
	if (m_DevNotifyMap.end() == itr)
	{
		LeaveCriticalSection(&m_DevNotifyMapSection);
		return E_FAIL;
	}

	DEVICE_HANDLE_NOTIFY_DATA& ndata = itr->second;

	m_DevNotifyMap.erase(itr);

	LeaveCriticalSection(&m_DevNotifyMapSection);

	XTLVERIFY( UnregisterDeviceNotification(DevNotifyHandle) );

	return S_OK;
}
Beispiel #19
0
HRESULT 
CNdasServiceDeviceEventHandler::pEnumerateNdasStoragePorts()
{
	HRESULT hr = S_OK;
	HDEVINFO hDevInfoSet = SetupDiGetClassDevs(
		&GUID_DEVINTERFACE_STORAGEPORT,
		NULL,
		NULL,
		DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);

	if (static_cast<HDEVINFO>(INVALID_HANDLE_VALUE) == hDevInfoSet)
	{
		hr = HRESULT_FROM_WIN32(GetLastError());
		XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_ERROR,
			"SetupDiCreateDeviceInfoList failed, hr=%x\n", hr);
		return hr;
	}

	for (DWORD index = 0; ; ++index)
	{
		SP_DEVICE_INTERFACE_DATA deviceInterfaceData = { sizeof(SP_DEVICE_INTERFACE_DATA) };

		BOOL success = SetupDiEnumDeviceInterfaces(
			hDevInfoSet, 
			NULL,
			&GUID_DEVINTERFACE_STORAGEPORT,
			index,
			&deviceInterfaceData);

		if (!success)
		{
			if (ERROR_NO_MORE_ITEMS != GetLastError())
			{
				hr = HRESULT_FROM_WIN32(GetLastError());
				XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_ERROR,
					"SetupDiEnumDeviceInterfaces failed, hr=%X\n", hr);
			}
			break;
		}

		DWORD requiredSize = 0;
		success = SetupDiGetDeviceInterfaceDetail(
			hDevInfoSet,
			&deviceInterfaceData,
			NULL,
			0,
			&requiredSize,
			NULL);

		if (success || ERROR_INSUFFICIENT_BUFFER != GetLastError())
		{
			if (success)
			{
				XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_ERROR,
					"SetupDiGetDeviceInterfaceDetail failed, no interface details\n");
			}
			else
			{
				XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_ERROR,
					"SetupDiGetDeviceInterfaceDetail failed, error=0x%X\n", GetLastError());
			}
			continue;
		}

		PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = 
			static_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(malloc(requiredSize));

		if (NULL == deviceInterfaceDetailData)
		{
			XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_ERROR,
				"malloc failed, bytes=%d\n", requiredSize);
			continue;
		}

		ZeroMemory(deviceInterfaceDetailData, requiredSize);
		deviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

		success = SetupDiGetDeviceInterfaceDetail(
			hDevInfoSet,
			&deviceInterfaceData,
			deviceInterfaceDetailData,
			requiredSize,
			NULL,
			NULL);

		if (!success)
		{
			XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_ERROR,
				"SetupDiGetDeviceInterfaceDetail failed, error=0x%X\n", GetLastError());

			free(deviceInterfaceDetailData);

			continue;
		}

		XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_INFORMATION,
			"StoragePort found, device=%ls\n", deviceInterfaceDetailData->DevicePath);

		HANDLE hDevice = CreateFile(
			deviceInterfaceDetailData->DevicePath,
			GENERIC_READ | GENERIC_WRITE,
			FILE_SHARE_READ | FILE_SHARE_WRITE,
			NULL,
			OPEN_EXISTING,
			FILE_ATTRIBUTE_DEVICE,
			NULL);

		if (INVALID_HANDLE_VALUE == hDevice)
		{
			XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_ERROR,
				"CreateFile failed, device=%ls, error=0x%X\n",
				deviceInterfaceDetailData->DevicePath, GetLastError());

			free(deviceInterfaceDetailData);

			continue;
		}

		DWORD slotNo = 0;
		HRESULT hr2 = pGetNdasSlotNumberFromDeviceHandle(hDevice, &slotNo);

		if (S_OK != hr2)
		{
			XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_WARNING,
				"StoragePort is not an NDAS Storage Port, hr=%x\n", hr2);

			XTLVERIFY( CloseHandle(hDevice) );
			free(deviceInterfaceDetailData);

			continue;
		}

		XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_INFORMATION,
			"NdasSlotNumber=%d\n", slotNo);

		//
		// As the ownership of the handler goes to the vector,
		// do not close the device handle here
		//

		AddDeviceNotificationHandle(
			hDevice, 
			CDeviceHandleNotifyData(
				DNT_STORAGE_PORT, 
				slotNo, 
				deviceInterfaceDetailData->DevicePath));

		XTLVERIFY( CloseHandle(hDevice) );
		free(deviceInterfaceDetailData);
	}

	XTLVERIFY( SetupDiDestroyDeviceInfoList(hDevInfoSet) );

	return hr;
}
Beispiel #20
0
LRESULT 
CNdasServiceDeviceEventHandler::
OnDeviceHandleRemoveComplete(
	PDEV_BROADCAST_HANDLE pdbch)
{
	//
	// Device Handle Remove Complete is called on Surprise Removal
	//

	XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_INFORMATION, 
		"OnDeviceHandleRemoveComplete: Device Handle %p, Notify Handle %p\n",
		pdbch->dbch_handle, pdbch->dbch_hdevnotify);

	DEVICE_HANDLE_NOTIFY_DATA notifyData;
	if (!FindDeviceHandle(pdbch->dbch_hdevnotify, &notifyData))
	{
		XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_INFORMATION, "Notify Handle is not registered.\n");
		return TRUE;
	}

	// Erase from the map
	XTLVERIFY(1 == m_DevNotifyMap.erase(pdbch->dbch_hdevnotify));

	BOOL fSuccess = ::UnregisterDeviceNotification(pdbch->dbch_hdevnotify);
	if (!fSuccess) 
	{
		XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_WARNING, 
			"Unregistering a device notification to %p failed.\n",
			pdbch->dbch_hdevnotify);
	}

	switch (notifyData.Type)
	{
	case DNT_STORAGE_PORT:
		{
			//
			// Remove removal is completed for NDAS SCSI Controller
			//
			if(m_service.NdasPortExists()) {
				break;
			}

			CNdasLogicalDevicePtr pLogDevice = 
				pGetNdasLogicalDeviceByNdasLocation(notifyData.NdasLocation);
			if (CNdasLogicalDeviceNullPtr == pLogDevice) 
			{
				XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_WARNING, 
					"Logical Device not found, ndasLocation=%d.\n", 
					notifyData.NdasLocation);
			}
			else
			{
				pLogDevice->OnUnmounted();
			}
		}
		break;
	case DNT_DISK:
	case DNT_CDROM:
		{
			//
			// Remove removal is completed for NDAS port
			//
			if(m_service.NdasPortExists() == FALSE) {
				break;
			}

			CNdasLogicalDevicePtr pLogDevice = 
				pGetNdasLogicalDeviceByNdasLocation(notifyData.NdasLocation);
			if (CNdasLogicalDeviceNullPtr == pLogDevice) 
			{
				XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_WARNING, 
					"Logical Device not found, ndasLocation=%d.\n", 
					notifyData.NdasLocation);
			}
			else
			{
				pLogDevice->OnUnmounted();
			}

			if(notifyData.Type == DNT_DISK) {
			XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_INFORMATION, 
				"Disk Remove Complete, ndasLocation=%d\n", 
				notifyData.NdasLocation);
			} else {
				XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_INFORMATION, 
					"CDROM Remove Complete, ndasLocation=%d\n", 
					notifyData.NdasLocation);
			}
		}
		break;
	case DNT_VOLUME:
		{
			XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_INFORMATION, 
				"Volume Remove Complete, ndasLocation=%d\n", 
				notifyData.NdasLocation);
		}
		break;
	default:
		// We do not care about other types at this time.
		break;
	}

	return TRUE;
}
Beispiel #21
0
 static void Release(HDEVINFO h) {
     XTL_SAVE_LAST_ERROR();
     XTLVERIFY(::SetupDiDestroyDeviceInfoList(h));
 }
Beispiel #22
0
STDMETHODIMP
CNdasDeviceRegistrar::Register(
    __in_opt DWORD SlotNo,
    __in const NDAS_DEVICE_ID& DeviceId,
    __in DWORD RegFlags,
    __in_opt const NDASID_EXT_DATA* NdasIdExtension,
    __in BSTR Name,
    __in ACCESS_MASK GrantedAccess,
    __in_opt const NDAS_OEM_CODE* NdasOemCode,
    __deref_out INdasDevice** ppNdasDevice)
{
    HRESULT hr;

    *ppNdasDevice = 0;

    NDAS_DEVICE_ID ndasDeviceId = DeviceId;

    //
    // this will lock this class from here
    // and releases the lock when the function returns;
    //
    CAutoLock<CLock> autolock(&m_DataLock);

    XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_INFORMATION,
              "Registering device %s at slot %d\n",
              CNdasDeviceId(DeviceId).ToStringA(), SlotNo);

    if (NULL == NdasIdExtension)
    {
        NdasIdExtension = &NDAS_ID_EXTENSION_DEFAULT;
    }

    //
    // Only DEFAULT and SEAGATE are currently implemented
    //
    if (NDAS_VID_SEAGATE != NdasIdExtension->VID	&&
            NDAS_VID_WINDWOS_RO != NdasIdExtension->VID		&&
            NDAS_VID_DEFAULT != NdasIdExtension->VID)
    {
        XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_ERROR,
                  "Unknown Vendor ID=0x%02X\n",
                  NdasIdExtension->VID);

        hr = NDASSVC_ERROR_UNKNOWN_VENDOR_ID;
        return hr;
    }

    ndasDeviceId.VID = NdasIdExtension->VID;

    // If SlotNo is zero, automatically assign it.
    // check slot number
    if (0 == SlotNo)
    {
        SlotNo = pLookupEmptySlot();
        if (0 == SlotNo)
        {
            return NDASSVC_ERROR_DEVICE_ENTRY_SLOT_FULL;
        }
    }
    else if (SlotNo > MAX_SLOT_NUMBER)
    {
        return NDASSVC_ERROR_INVALID_SLOT_NUMBER;
    }

    // check and see if the slot is occupied
    if (m_slotbit[SlotNo])
    {
        return NDASSVC_ERROR_SLOT_ALREADY_OCCUPIED;
    }

    // find an duplicate address
    {
        CComPtr<INdasDevice> pExistingDevice;
        if (SUCCEEDED(get_NdasDevice(&ndasDeviceId, &pExistingDevice)))
        {
            return NDASSVC_ERROR_DUPLICATE_DEVICE_ENTRY;
        }
    }

    // register
    CComObject<CNdasDevice>* pNdasDeviceInstance;
    hr = CComObject<CNdasDevice>::CreateInstance(&pNdasDeviceInstance);
    if (FAILED(hr))
    {
        return hr;
    }

    hr = pNdasDeviceInstance->Initialize(
             SlotNo, ndasDeviceId, RegFlags, NdasIdExtension);
    if (FAILED(hr))
    {
        XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_ERROR,
                  "Device initialization failed, error=0x%X\n", GetLastError());
        return hr;
    }

    CComPtr<INdasDevice> pNdasDevice(pNdasDeviceInstance);

    COMVERIFY(pNdasDevice->put_Name(Name));
    COMVERIFY(pNdasDevice->put_GrantedAccess(GrantedAccess));
    if (NdasOemCode)
    {
        COMVERIFY(pNdasDevice->put_OemCode(NdasOemCode));
    }

    m_slotbit[SlotNo] = true;

    bool insertResult;

    m_NdasDevices.Add(pNdasDevice);

    XTLVERIFY( m_deviceSlotMap.insert(std::make_pair(SlotNo, pNdasDevice)).second );
    //DeviceSlotMap::value_type(SlotNo, pNdasDevice)).second;

    XTLVERIFY( m_deviceIdMap.insert(std::make_pair(ndasDeviceId, pNdasDevice)).second );
    //DeviceIdMap::value_type(ndasDeviceId, pNdasDevice)).second;

    XTLASSERT(m_deviceSlotMap.size() == m_deviceIdMap.size());

    //
    // When NdasIdExtension is NULL, NDAS_ID_EXTENSION_DEFAULT is assigned already
    //

    if (RegFlags & NDAS_DEVICE_REG_FLAG_VOLATILE)
    {
    }
    else
    {
        BOOL success;
        XTL::CStaticStringBuffer<30> containerName(_T("Devices\\%04d"), SlotNo);

        if (0 != memcmp(&NDAS_ID_EXTENSION_DEFAULT, NdasIdExtension, sizeof(NDASID_EXT_DATA)))
        {
            NDAS_DEVICE_ID_REG_DATA regData = {0};
            regData.DeviceId = ndasDeviceId;
            regData.NdasIdExtension = *NdasIdExtension;

            success = _NdasSystemCfg.SetSecureValueEx(
                          containerName,
                          _T("DeviceID2"),
                          &regData,
                          sizeof(regData));
        }
        else
        {
            success = _NdasSystemCfg.SetSecureValueEx(
                          containerName,
                          _T("DeviceID"),
                          &ndasDeviceId,
                          sizeof(ndasDeviceId));
        }

        if (!success)
        {
            XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_WARNING,
                      "Writing registration entry to the registry failed at %ls, error=0x%X\n",
                      containerName.ToString(), GetLastError());
        }

        success = _NdasSystemCfg.SetSecureValueEx(
                      containerName,
                      _T("RegFlags"),
                      &RegFlags,
                      sizeof(RegFlags));

        if (!success)
        {
            XTLTRACE2(NDASSVC_NDASDEVICEREGISTRAR, TRACE_LEVEL_WARNING,
                      "Writing registration entry to the registry failed at %ls, error=0x%X\n",
                      containerName.ToString(), GetLastError());
        }
    }

    BOOL publishEvent = !m_fBootstrapping;

    autolock.Release();

    //
    // During bootstrapping, we do not publish this event
    // Bootstrap process will publish an event later
    //

    if (publishEvent)
    {
        (void) pGetNdasEventPublisher().DeviceEntryChanged();
    }

    *ppNdasDevice = pNdasDevice.Detach();

    return S_OK;
}
Beispiel #23
0
BOOL
CreateNdasCommandServerDefaultDACL(
	__inout LPSECURITY_ATTRIBUTES SecurityAttributes)
{
#define NDASSVC_ALLOW_INTERACTIVE_USERS
// Anonymous in SDDL in Windows 2000 does not work
// #define NDASSVC_DENY_ANONYMOUS

	// Define the SDDL for the DACL. This example sets 
	// the following access:
	//     Built-in guests are denied all access.
	//     Anonymous Logon is denied all access.
	//     Authenticated Users are allowed read/write/execute access.
	//     Administrators are allowed full control.
	// Modify these values as needed to generate the proper
	// DACL for your application. 
#if 0
	LPCWSTR securityDescriptor = 
		L"D:"                   // Discretionary ACL
		L"(D;OICI;GA;;;BG)"     // Deny access to Built-in Guests
		L"(D;OICI;GA;;;AN)"     // Deny access to Anonymous Logon
		L"(A;OICI;GRGWGX;;;AU)" // Allow read/write/execute to Authenticated Users
		L"(A;OICI;GA;;;BA)";    // Allow full control to Administrators
#else
	LPCTSTR securityDescriptor = 
		SDDL_DACL 
		SDDL_DELIMINATOR
		// Deny access to Built-in Guests
		SDDL_ACE_BEGIN
			SDDL_ACCESS_DENIED SDDL_SEPERATOR
			SDDL_OBJECT_INHERIT SDDL_CONTAINER_INHERIT SDDL_SEPERATOR
			SDDL_GENERIC_ALL SDDL_SEPERATOR
			SDDL_SEPERATOR
			SDDL_SEPERATOR
			SDDL_BUILTIN_GUESTS
		SDDL_ACE_END
		//
		// Anonymous DOES NOT work in Windows 2000
		//
#ifdef NDASSVC_DENY_ANONYMOUS
		// Deny access to Anonymous
		SDDL_ACE_BEGIN
			SDDL_ACCESS_DENIED SDDL_SEPERATOR
			SDDL_OBJECT_INHERIT SDDL_CONTAINER_INHERIT SDDL_SEPERATOR
			SDDL_GENERIC_ALL SDDL_SEPERATOR
			SDDL_SEPERATOR
			SDDL_SEPERATOR
			SDDL_ANONYMOUS
		SDDL_ACE_END
#endif
#ifdef NDASSVC_ALLOW_INTERACTIVE_USERS
		// Allow RWX to Interactive Users
		SDDL_ACE_BEGIN
			SDDL_ACCESS_ALLOWED SDDL_SEPERATOR
			SDDL_OBJECT_INHERIT SDDL_CONTAINER_INHERIT SDDL_SEPERATOR
			SDDL_GENERIC_READ SDDL_GENERIC_WRITE SDDL_GENERIC_EXECUTE SDDL_SEPERATOR
			SDDL_SEPERATOR
			SDDL_SEPERATOR
			SDDL_INTERACTIVE
		SDDL_ACE_END
#endif
		// Allow Full Control to Administrators
		SDDL_ACE_BEGIN
			SDDL_ACCESS_ALLOWED SDDL_SEPERATOR
			SDDL_OBJECT_INHERIT SDDL_CONTAINER_INHERIT SDDL_SEPERATOR
			SDDL_GENERIC_ALL SDDL_SEPERATOR
			SDDL_SEPERATOR
			SDDL_SEPERATOR
			SDDL_BUILTIN_ADMINISTRATORS
		SDDL_ACE_END
		// Allow Full Control to Local System
		SDDL_ACE_BEGIN
			SDDL_ACCESS_ALLOWED SDDL_SEPERATOR
			SDDL_OBJECT_INHERIT SDDL_CONTAINER_INHERIT SDDL_SEPERATOR
			SDDL_GENERIC_ALL SDDL_SEPERATOR
			SDDL_SEPERATOR
			SDDL_SEPERATOR
			SDDL_LOCAL_SYSTEM
		SDDL_ACE_END;
#endif
	if (NULL == SecurityAttributes)
	{
		XTLASSERT(FALSE);
		return FALSE;
	}

	BOOL success;

	XTLVERIFY( 
	success = ConvertStringSecurityDescriptorToSecurityDescriptor(
			securityDescriptor,
			SDDL_REVISION_1,
			&(SecurityAttributes->lpSecurityDescriptor),
			NULL) );

	return success;

}
Beispiel #24
0
DWORD 
CNdasCommandServer::ServiceCommand(HANDLE hStopEvent)
{

	// Named Pipe Connection Event
	XTL::AutoObjectHandle hConnectEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);

	if (hConnectEvent.IsInvalid()) 
	{
		// Log Error Here
		XTLTRACE2(NDASSVC_CMDSERVER, TRACE_LEVEL_ERROR,
		 "Creating ndascmd connection event failed, error=0x%X\n",
		 GetLastError());
		return 1;
	}

	// Default Security Settings
	SECURITY_ATTRIBUTES securityAttributes;
	BOOL success = CreateNdasCommandServerDefaultDACL(&securityAttributes);
	if (!success)
	{
		XTLTRACE2(NDASSVC_CMDSERVER, TRACE_LEVEL_ERROR,
			"CreateNdasCommandServerDefaultDACL failed, error=0x%X\n",
			GetLastError());
		return 2;
	}

	// Create a named pipe instance
	XTL::AutoFileHandle hPipe = ::CreateNamedPipe(
		PipeName,
		PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // | FILE_FLAG_FIRST_PIPE_INSTANCE,
		PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
		MaxPipeInstances, 
		0,
		0,
		PipeTimeout,
		&securityAttributes);

	if (hPipe.IsInvalid()) 
	{
		// Log Error Here
		XTLTRACE2(NDASSVC_CMDSERVER, TRACE_LEVEL_ERROR,
			"Creating pipe server failed, error=0x%X\n", GetLastError());
		return 2;
	}

	HANDLE waitHandles[] = { hStopEvent, hConnectEvent };
	const DWORD nWaitHandles = RTL_NUMBER_OF(waitHandles);

	while (TRUE) 
	{
		// Initialize overlapped structure
		OVERLAPPED overlapped = {0};
		overlapped.hEvent = hConnectEvent;
		XTLVERIFY( ::ResetEvent(hConnectEvent) );

		CNamedPipeTransport namePipeTransport(hPipe);
		CNamedPipeTransport* pTransport = &namePipeTransport;

		BOOL fSuccess = pTransport->Accept(&overlapped);
		if (!fSuccess) 
		{ 
			XTLTRACE2(NDASSVC_CMDSERVER, TRACE_LEVEL_ERROR,
				"Transport Accept (Named Pipe) failed, error=0x%X\n", GetLastError());
			break;
		}

		DWORD waitResult = ::WaitForMultipleObjects(
			nWaitHandles, waitHandles, FALSE, INFINITE);

		switch (waitResult) 
		{
		case WAIT_OBJECT_0: // Terminate Thread Event
			return 0;
		case WAIT_OBJECT_0 + 1: // Connect Event
			//
			// Process the request
			// (Safely ignore error)
			//
			{
				CNdasCommandProcessor processor(m_service, pTransport);
				if (!processor.Process())
				{
					XTLTRACE2(NDASSVC_CMDSERVER, TRACE_LEVEL_ERROR,
						"CommandProcess failed, error=0x%X\n", GetLastError());
				}
				// After processing the request, reset the pipe instance
				XTLVERIFY( ::FlushFileBuffers(hPipe) );
				XTLVERIFY( ::DisconnectNamedPipe(hPipe) );
			}			
			break;
		default:
			XTLTRACE2(NDASSVC_CMDSERVER, TRACE_LEVEL_ERROR,
				"WaitForMultipleObjects failed, waitResult=0x%X error=0x%X\n",
				waitResult, GetLastError());
			XTLASSERT(FALSE);
		}
	}

	return 0;
}
DWORD
CNdasEventMonitor::ThreadStart(HANDLE hStopEvent)
{
	CCoInitialize coinit(COINIT_MULTITHREADED);

	// 15 sec = 10,000,000 nanosec
	// negative value means relative time
	LARGE_INTEGER liDueTime;
	liDueTime.QuadPart = - 10 * 1000 * 1000;

	BOOL success = ::SetWaitableTimer(
		m_HeartbeatMonitorTimer, 
		&liDueTime, 
		HEARTBEAT_MONITOR_INTERVAL, 
		NULL, 
		NULL, 
		FALSE);

	if (!success) 
	{
		XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_ERROR,
			"Setting waitable timer failed, error=0x%X\n", GetLastError());
	}

	XTLVERIFY( ::ResetEvent(m_NdasLogicalUnitSetChanged) );

	std::vector<HANDLE> waitHandles;
	waitHandles.reserve(20);

	// Lock-free copy of the devices and logDevices
	CInterfaceArray<INdasDevice> ndasDevices;
	CInterfaceArray<INdasLogicalUnit> ndasLogicalUnits;

	while (true)
	{
		//
		// Copy m_NdasDevices and m_NdasLogicalUnits to devices and logDevices
		// for lock free accesses
		//
		// DEVICE READER LOCK REGION
		{
			XTL::CReaderLockHolder holder(m_NdasDeviceDataLock);
			ndasDevices.Copy(m_NdasDevices);
		}
		{
			XTL::CReaderLockHolder holder(m_NdasLogicalUnitDataLock);
			ndasLogicalUnits.Copy(m_NdasLogicalUnits);
		}
		// DEVICE READER LOCK REGION

		//
		// Recreate wait handles
		//
		size_t ndasLogicalUnitCount = ndasLogicalUnits.GetCount();
		waitHandles.resize(3 + ndasLogicalUnitCount * 2);

		waitHandles[0] = hStopEvent;
		waitHandles[1] = m_NdasLogicalUnitSetChanged;
		waitHandles[2] = m_HeartbeatMonitorTimer;

		// Disconnect events i=[3 ...3+nLogDevices)
		// Alarm Events events i=[3+nLogDevices ... 3+2*nLogDevices)
		for (size_t index = 0; index < ndasLogicalUnitCount; ++index)
		{
			INdasLogicalUnit* pNdasLogicalUnit = ndasLogicalUnits.GetAt(index);
			waitHandles[3 + index] = 
				NdasLogicalUnitDisconnectEvent()(pNdasLogicalUnit);
			waitHandles[3 + index + ndasLogicalUnitCount] = 
				NdasLogicalUnitAlarmEvent()(pNdasLogicalUnit);
		}

		DWORD nWaitHandles = waitHandles.size();

		DWORD waitResult = ::WaitForMultipleObjects(
			nWaitHandles, 
			&waitHandles[0], 
			FALSE, 
			INFINITE);

		if (WAIT_OBJECT_0 == waitResult)
		{
			// Terminate Thread Event
			XTLVERIFY( ::CancelWaitableTimer(m_HeartbeatMonitorTimer) );
			return 0;
		}
		else if (WAIT_OBJECT_0 + 1 == waitResult) 
		{
			// Logical device set change event
			XTLVERIFY( ::ResetEvent(m_NdasLogicalUnitSetChanged) );
			continue;
		} 
		else if (WAIT_OBJECT_0 + 2 == waitResult) 
		{
			// Heartbeat Monitor Timer Event
			AtlForEach(ndasDevices, InvokeTimerEventSink<INdasDevice>());
			AtlForEach(ndasLogicalUnits, InvokeTimerEventSink<INdasLogicalUnit>());
		}
		else if (
			waitResult >= WAIT_OBJECT_0 + 3 &&
			waitResult < WAIT_OBJECT_0 + 3 + ndasLogicalUnitCount)
		{
			XTLVERIFY( ::ResetEvent(waitHandles[waitResult - WAIT_OBJECT_0]) );
			// Disconnect Event
			DWORD n = waitResult - (WAIT_OBJECT_0 + 3);
			OnLogicalDeviceDisconnected(ndasLogicalUnits[n]);
		} 
		else if (
			waitResult >= WAIT_OBJECT_0 + 3 + ndasLogicalUnitCount &&
			waitResult < WAIT_OBJECT_0 + 3 + 2 * ndasLogicalUnitCount)
		{
			XTLVERIFY( ::ResetEvent(waitHandles[waitResult - WAIT_OBJECT_0]) );
			// Alarm Event
			DWORD n = waitResult - (WAIT_OBJECT_0 + 3 + ndasLogicalUnitCount);
			OnLogicalDeviceAlarmed(ndasLogicalUnits[n]);
		}
		else 
		{
			XTLASSERT(FALSE);
		}
	}
}
Beispiel #26
0
DWORD 
CNdasCommandServer::
ThreadStart(LPVOID lpParam)
{
	HANDLE hStopEvent = static_cast<HANDLE>(lpParam);

	CmdWorkItemVector workItems;
	workItems.reserve(MaxPipeInstances);

	size_t size = workItems.size();
	XTLASSERT(0 == size);
	std::generate_n(
		std::back_inserter(workItems), 
		MaxPipeInstances, 
		pWorkItemPtrGenerator);
	size = workItems.size();
	XTLASSERT(MaxPipeInstances == size);

	DWORD nWorkItems = 0;

	for (DWORD i = 0; i < MaxPipeInstances; ++i)
	{
		CmdWorkItemPtr p = workItems[i];
		BOOL fSuccess = p->QueueUserWorkItemEx(
			this, 
			&CNdasCommandServer::CommandProcessStart, 
			hStopEvent, 
			WT_EXECUTELONGFUNCTION);
		if (fSuccess)
		{
			++nWorkItems;
		}
		else
		{
			XTLTRACE2(NDASSVC_CMDSERVER, TRACE_LEVEL_ERROR,
				"Starting work item (%d/%d) failed, error=0x%X\n",
				i + 1, MaxPipeInstances, GetLastError());
		}
	}

	// Release semaphore to start workers (semaphore increment)
	LONG prev;
	XTLVERIFY( ::ReleaseSemaphore(m_hProcSemaphore, nWorkItems, &prev) );
	XTLASSERT( 0 == prev );

	// Wait for stop event
	XTLVERIFY(WAIT_OBJECT_0 == ::WaitForSingleObject(hStopEvent, INFINITE));

	// Stopped and waits for user work items
	DWORD finished = 0;
	while (finished < nWorkItems)
	{
		::Sleep(0);
		DWORD waitResult = ::WaitForSingleObject(m_hProcSemaphore, 0);
		if (waitResult == WAIT_OBJECT_0)
		{
			XTLTRACE2(NDASSVC_CMDSERVER, TRACE_LEVEL_INFORMATION,
				"Command Process work item finished (%d/%d).\n", 
				finished + 1, nWorkItems);
			++finished;
		}
		XTLVERIFY(WAIT_OBJECT_0 == waitResult || WAIT_TIMEOUT == waitResult);
	}

	// Now Finally this thread can stop
	return 0;
}
Beispiel #27
0
DWORD
CNdasService::Impl::ThreadStart(LPVOID)
{
	//
	//	Stop NdasBus auto-plugin feature to take over plugin facility.
	//

	BOOL fSuccess = LsBusCtlStartStopRegistrarEnum(FALSE, NULL);
	XTLASSERT(fSuccess);

	//////////////////////////////////////////////////////////////////////////
	// Get the initialized instance
	//////////////////////////////////////////////////////////////////////////

	if (!InitializeInstances())
	{
		OnServiceStop();
		return 1;
	}

	//////////////////////////////////////////////////////////////////////////
	// Bootstrap registrar from the registry
	//////////////////////////////////////////////////////////////////////////

	XTLVERIFY( m_cDeviceRegistrar.Bootstrap() );

	//////////////////////////////////////////////////////////////////////////
	// Start Queuing Work Items
	//////////////////////////////////////////////////////////////////////////

	m_nWorkItems = 0;
	if (!StartWorkItems(m_nWorkItems))
	{
		OnServiceStop();
		return 1;
	}

	// Release semaphore to start workers (semaphore increment)
	LONG prev;
	XTLVERIFY( ::ReleaseSemaphore(m_hWorkItemSemaphore, m_nWorkItems, &prev) );
	XTLASSERT( 0 == prev );

	//////////////////////////////////////////////////////////////////////////
	// Start Command Processor Thread
	//////////////////////////////////////////////////////////////////////////

	if (!m_wiCmdServer.CreateThreadEx(
			&m_cCmdServer, 
			&CNdasCommandServer::ThreadStart,
			LPVOID(m_hStopServiceEvent)))
	{
		OnServiceStop();
		return 1;
	}

	//////////////////////////////////////////////////////////////////////////
	// Initialization thread is done
	//////////////////////////////////////////////////////////////////////////

	return 0;
}
Beispiel #28
0
DWORD
CNdasService::Impl::OnServiceStop()
{
	//////////////////////////////////////////////////////////////////////////
	// We should report the SCM that the service is stopping
	// Otherwise, the service will terminate the thread.
	// And we'll get ACCESS VIOLATION ERROR!
	//////////////////////////////////////////////////////////////////////////

	XTLTRACE("Service is stopping...\n");

	ReportServiceStopPending(1000);
	XTLVERIFY( ::SetEvent(m_hStopServiceEvent) );

	// Yield to other threads to finish themselves.
	::Sleep(0);

	//////////////////////////////////////////////////////////////////////////
	// Wait for the command processor thread to stop
	//////////////////////////////////////////////////////////////////////////

	XTLTRACE("Waiting for worker threads to stop....\n");

	DWORD waitResult = WAIT_TIMEOUT;
	while (WAIT_OBJECT_0 != waitResult)
	{
		ReportServiceStopPending(3000);
		// yield to work threads for them to handle their terminations
		::Sleep(0);
		waitResult = ::WaitForSingleObject(m_wiCmdServer.GetThreadHandle(), 3000);
		XTLVERIFY(WAIT_OBJECT_0 == waitResult || WAIT_TIMEOUT == waitResult);
		XTLTRACE("Waiting for command processors to stop in 3 seconds....\n");
	}
	
	XTLTRACE("Command processors stopped....\n");

	//////////////////////////////////////////////////////////////////////////
	// Wait for the work items to stop
	//////////////////////////////////////////////////////////////////////////

	DWORD finished = 0;
	while (finished < m_nWorkItems)
	{
		ReportServiceStopPending(1500);
		// yield to work threads for them to handle their terminations
		::Sleep(0);
		DWORD waitResult = ::WaitForSingleObject(m_hWorkItemSemaphore, 1000);
		if (waitResult == WAIT_OBJECT_0)
		{
			++finished;
			XTLTRACE("(%d/%d) WorkItems stopped...\n", finished, m_nWorkItems);
		}
		XTLVERIFY(WAIT_OBJECT_0 == waitResult || WAIT_TIMEOUT == waitResult);
	}

	//////////////////////////////////////////////////////////////////////////
	// All threads and work items are done
	//////////////////////////////////////////////////////////////////////////

	XTLTRACE("All work items stopped....\n");
	XTLTRACE("Reporting to the SCM that the service is stopped....\n");

	m_cDeviceEventHandler.Uninitialize();

	m_cDeviceRegistrar.Cleanup();
	m_cLogDeviceManager.Cleanup();

	ReportServiceStopped();

	return NO_ERROR;
}
Beispiel #29
0
BOOL
CNdasUnitDeviceCreator::ReadBACL(BLOCK_ACCESS_CONTROL_LIST** ppBACL, UINT32 BACLSize)
{
    //
    // ppBACL will be set only if this function succeed.
    //

    UINT32 ElementCount =
        (BACLSize - (sizeof(BLOCK_ACCESS_CONTROL_LIST) - sizeof(BLOCK_ACCESS_CONTROL_LIST_ELEMENT))) /
        sizeof(BLOCK_ACCESS_CONTROL_LIST_ELEMENT);

    // allocate pBACL to fit sector align
    PBLOCK_ACCESS_CONTROL_LIST pBACL = reinterpret_cast<PBLOCK_ACCESS_CONTROL_LIST>(
                                           HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 512 * BACL_SECTOR_SIZE(ElementCount)));

    if (NULL == pBACL)
    {
        // Out of memory!
        return FALSE;
    }

    BOOL fSuccess = m_devComm.ReadDiskBlock(
                        reinterpret_cast<PBYTE>(pBACL),
                        NDAS_BLOCK_LOCATION_BACL,
                        BACL_SECTOR_SIZE(ElementCount));

    //
    // Regardless of the existence,
    // Disk Block should be read.
    // Failure means communication error or disk error
    //
    if (!fSuccess)
    {
        XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR,
                  "ReadDiskBlock failed, block=%I64d, error=0x%X\n",
                  NDAS_BLOCK_LOCATION_BACL, GetLastError());

        XTLVERIFY( HeapFree(GetProcessHeap(), 0, pBACL) );
        return FALSE;
    }

    //
    // check structure
    //
    if (BACL_SIGNATURE != pBACL->Signature ||
            BACL_VERSION < pBACL->Version ||
            crc32_calc((unsigned char *)&pBACL->Elements[0],
                       sizeof(BLOCK_ACCESS_CONTROL_LIST_ELEMENT) * (pBACL->ElementCount)) !=
            pBACL->crc)
    {
        XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR,
                  "On-disk BACL information is invalid!\n");

        XTLVERIFY( HeapFree(GetProcessHeap(), 0, pBACL) );
        return FALSE;
    }

    *ppBACL = pBACL;

    return TRUE;
}
Beispiel #30
0
BOOL
CNdasUnitDeviceCreator::ReadDIB(NDAS_DIB_V2** ppDIBv2)
{
    //
    // ppDIBv2 will be set only if this function succeed.
    //

    PNDAS_DIB_V2 pDIBv2 = reinterpret_cast<PNDAS_DIB_V2>(
                              HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 512));

    if (NULL == pDIBv2)
    {
        XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR,
                  "ReadDiskBlock failed, error=0x%X\n",
                  GetLastError());

        return FALSE;
    }

    BOOL fSuccess = m_devComm.ReadDiskBlock(
                        reinterpret_cast<PBYTE>(pDIBv2),
                        NDAS_BLOCK_LOCATION_DIB_V2);

    //
    // Regardless of the existence,
    // Disk Block should be read.
    // Failure means communication error or disk error
    //
    if (!fSuccess)
    {
        XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR,
                  "ReadDiskBlock failed, error=0x%X\n",
                  GetLastError());

        XTLVERIFY( HeapFree(GetProcessHeap(), 0, pDIBv2) );

        return FALSE;
    }

    //
    // check signature
    //

    if(NDAS_DIB_V2_SIGNATURE != pDIBv2->Signature ||
            pDIBv2->crc32 != crc32_calc((unsigned char *)pDIBv2,
                                        sizeof(pDIBv2->bytes_248)) ||
            pDIBv2->crc32_unitdisks != crc32_calc((unsigned char *)pDIBv2->UnitDisks,
                    sizeof(pDIBv2->UnitDisks)))
    {
        //
        // Read DIBv1
        //

        fSuccess = ReadDIBv1AndConvert(pDIBv2);

        if (!fSuccess)
        {
            XTLVERIFY( HeapFree(GetProcessHeap(), 0, pDIBv2) );
            return FALSE;
        }

        if ( ! IsConsistentDIB(pDIBv2) )
        {
            // Inconsistent DIB will be reported as single
            InitializeDIBv2AsSingle(pDIBv2);
        }

        *ppDIBv2 = pDIBv2;
        return TRUE;
    }

    //
    // check version
    //
    if(IS_HIGHER_VERSION_V2(*pDIBv2))
    {
        XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR,
                  "Unsupported version V2.\n");

        XTLVERIFY( HeapFree(GetProcessHeap(), 0, pDIBv2) );
        return FALSE;
    }

    //
    // TODO: Lower version process (future code) ???
    //
    if(0)
    {
        XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR,
                  "lower version V2 detected\n");
    }

    //
    // read additional locations if needed
    //
    if (pDIBv2->nDiskCount + pDIBv2->nSpareCount > NDAS_MAX_UNITS_IN_V2)
    {

        UINT32 nTrailSectorCount =
            GET_TRAIL_SECTOR_COUNT_V2(pDIBv2->nDiskCount + pDIBv2->nSpareCount);

        SIZE_T dwBytes = sizeof(NDAS_DIB_V2) + 512 * nTrailSectorCount;

        LPVOID ptr = HeapReAlloc(
                         GetProcessHeap(),
                         HEAP_ZERO_MEMORY,
                         pDIBv2,
                         dwBytes);

        if (NULL == ptr)
        {
            XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR,
                      "HeapReAlloc failed, bytes=%d\n", dwBytes);

            // When HeapReAlloc fails, pDIBv2 should be freed
            XTLVERIFY( HeapFree(GetProcessHeap(), 0, pDIBv2) );

            return FALSE;
        }

        pDIBv2 = reinterpret_cast<PNDAS_DIB_V2>(ptr);

        for(DWORD i = 0; i < nTrailSectorCount; i++) {

            fSuccess = m_devComm.ReadDiskBlock(
                           reinterpret_cast<PBYTE>(pDIBv2) + sizeof(NDAS_DIB_V2) + 512 * i,
                           NDAS_BLOCK_LOCATION_ADD_BIND + i);

            if(!fSuccess)
            {
                XTLTRACE2(NDASSVC_NDASUNITDEVICE, TRACE_LEVEL_ERROR,
                          "Reading additional block failed, block=%d, error=0x%X\n",
                          NDAS_BLOCK_LOCATION_ADD_BIND + i, GetLastError());

                XTLVERIFY( HeapFree(GetProcessHeap(), 0, pDIBv2) );

                return FALSE;
            }
        }
    }

    // Virtual DVD check. Not supported ATM.

    //
    // DIB Consistency Check
    //
    if ( ! IsConsistentDIB(pDIBv2) )
    {
        // Inconsistent DIB will be reported as single
        InitializeDIBv2AsSingle(pDIBv2);
    }

    *ppDIBv2 = pDIBv2;

    return TRUE;
}