[ros-kernel] Bug in NtAllocateVirtualMemory

Filip Navara xnavara at volny.cz
Sun Feb 1 00:04:09 CET 2004


Hi,

I need help some help from educated kernel person again. I found that 
the attached code from ATL doesn't work under ReactOS. The cause is that 
in ReactOS it's not possible to call NtAllocateVirtualMemory on 
MEMORY_AREA_SECTION_VIEW memory area with specified prefered base 
address and MEM_COMMIT flag. I have no idea how this situation should be 
handled correctly, so I'm using this hack right now:

    MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
                           BaseAddress);
   
+    if (MemoryArea != NULL &&
+        MemoryArea->Type == MEMORY_AREA_SECTION_VIEW &&
+        MemoryArea->Length >= RegionSize)
+      {
+        MmUnlockAddressSpace(AddressSpace);
+        ObDereferenceObject(Process);
+        return STATUS_SUCCESS;
+      }
    else if (MemoryArea != NULL &&
         MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY &&
         MemoryArea->Length >= RegionSize)

Regards,
Filip

-------------- next part --------------
bool CAtlAllocator::Init(const CHAR *pszFileName, DWORD dwMaxSize)
{
	// We're relying on syncronization provided by the startup code (CRT DllMain/WinMain)
	Close();

	ATLASSERT(!m_hMap && !m_pBufferStart);

	HANDLE hThreadToken = NULL;
	__try
	{
		if( !(GetVersion()&0x80000000) )
		{
			// If we're being loaded while impersonating a different client, 
			// we need to revert to self before we open the shared memory section
			OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE|TOKEN_DUPLICATE, FALSE, &hThreadToken);
			if( hThreadToken != NULL )
			{
				if( !RevertToSelf() )
				{
					CloseHandle(hThreadToken);
					hThreadToken = NULL;
					__leave;
				}
			}
		}
		// Use a NULL SECURITY_ATTRIBUTES structure to get the default DACL.
		m_hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL,
			PAGE_READWRITE | SEC_RESERVE, 0, dwMaxSize, pszFileName);
		if(!m_hMap)
			__leave;
		DWORD dwErr = ::GetLastError();

		m_pBufferStart = (BYTE *)
			MapViewOfFile(m_hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
		if(!m_pBufferStart)
			__leave;

		SYSTEM_INFO si;
		GetSystemInfo(&si);

		if(dwErr == ERROR_ALREADY_EXISTS)
		{
			m_pProcess = reinterpret_cast<CAtlTraceProcess *>(m_pBufferStart);

			// Looks like it's already mapped into this process space.
			// Let's do some checking...
			if(IsBadReadPtr(m_pProcess, sizeof(CAtlTraceProcess)) ||
				IsBadReadPtr(m_pProcess->Base(), sizeof(CAtlTraceProcess)) ||
				0 != memcmp(m_pBufferStart, m_pProcess->Base(), m_pProcess->m_dwFrontAlloc))
			{
				// something's not right
				__leave;
			}

			// sure looks valid
			m_pProcess->IncRef();
			m_pProcess = static_cast<CAtlTraceProcess *>(m_pProcess->Base());

			UnmapViewOfFile(m_pBufferStart);
			m_pBufferStart = reinterpret_cast<BYTE *>(m_pProcess);
		}
		else
		{
			// This is just in case sizeof(CAtlTraceProcess) is
			// ever > dwPageSize (doubtful that could ever
			// happen, but it's easy enough to avoid here)
			DWORD dwCurrAlloc = si.dwPageSize;
			while(dwCurrAlloc < sizeof(CAtlTraceProcess))
				dwCurrAlloc += si.dwPageSize;

			if(!VirtualAlloc(m_pBufferStart, dwCurrAlloc, MEM_COMMIT, PAGE_READWRITE))
				__leave;

			m_pProcess = new(m_pBufferStart) CAtlTraceProcess(dwMaxSize);
			m_pProcess->m_dwFrontAlloc = dwCurrAlloc;
			m_pProcess->m_dwCurrFront = sizeof(CAtlTraceProcess);
		}
		m_dwPageSize = si.dwPageSize;
		m_bValid = true;
	}
	__finally
	{
		if( hThreadToken != NULL )
		{
			// Go back to impersonating whomever we were impersonating
			BOOL bSuccess;
			bSuccess = SetThreadToken(NULL, hThreadToken);
			ATLASSERT( bSuccess );
			CloseHandle( hThreadToken );
		}

		if(!m_bValid)
		{
			if(m_pBufferStart)
			{
				UnmapViewOfFile(m_pBufferStart);
				m_pBufferStart = NULL;
			}

			if(m_hMap)
			{
				CloseHandle(m_hMap);
				m_hMap = NULL;
			}
		}
	}
	return m_bValid;
}


More information about the Ros-kernel mailing list