📄 mapfile.c
字号:
// Special treatment of uncompressed files in ROM: Map directly from ROM
// without using any RAM.
if ((hFile != INVALID_HANDLE_VALUE)
&& !(flProtect & PAGE_READWRITE)
&& GetFileInformationByHandle(hFile, &info)
&& (info.dwFileAttributes & FILE_ATTRIBUTE_INROM)
&& !(info.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED)
&& IS_ROMFILE_OID(info.dwOID)
// Only trusted applications can map directly from ROM because they may
// get access to nearby data
&& (SC_CeGetCallerTrust() == OEM_CERTIFY_TRUST)) {
DEBUGMSG(ZONE_PAGING || ZONE_MAPFILE, (TEXT("CreateFileMapping: map file directly from ROM\r\n")));
bDirectROM = TRUE;
bPage = FALSE;
dwMapLen = 0; // Will be figured out later
}
ClearNKCallOut (pCurThread);
bNoAutoFlush = (flProtect & PAGE_INTERNALDBMAPPING) ? 1 : 0;
flProtect &= ~(SEC_COMMIT | PAGE_INTERNALDBMAPPING);
// Remove non-database mappings from mapper cleanup list
if ((hFile != INVALID_HANDLE_VALUE) && !bNoAutoFlush) {
CLEANEVENT *pce, *pce2;
EnterCriticalSection(&MapNameCS);
if (pce = pCFMCleanup) {
if (pce->base == hFile) {
pCFMCleanup = pce->ceptr;
FreeMem(pce, HEAP_CLEANEVENT);
} else {
while (pce->ceptr && (pce->ceptr->base != hFile))
pce = pce->ceptr;
if (pce2 = pce->ceptr) {
pce->ceptr = pce2->ceptr;
FreeMem(pce2, HEAP_CLEANEVENT);
}
}
}
LeaveCriticalSection(&MapNameCS);
}
//
// Determine the size the map should have
//
if (!bDirectROM) {
if ((hFile != INVALID_HANDLE_VALUE)
&& ((dwFileLen = SetFilePointer(hFile, 0, 0, FILE_END)) == 0xffffffff)) {
KernelCloseHandle(hFile);
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
return 0;
}
// Adjust based on parameters
if ((hFile == INVALID_HANDLE_VALUE) || dwMaxSizeLow)
dwMapLen = dwMaxSizeLow;
else
dwMapLen = dwFileLen;
if (dwMapLen & 0x80000000) {
KernelCloseHandle(hFile);
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
return 0;
}
// Extend the file to the new size, if necessary
if ((hFile != INVALID_HANDLE_VALUE) && (dwFileLen < dwMapLen)) {
if (!bNoAutoFlush && ((SetFilePointer(hFile, dwMapLen, 0, FILE_BEGIN) != dwMapLen)
|| !SetEndOfFile(hFile))) {
KernelCloseHandle(hFile);
KSetLastError(pCurThread, ERROR_ACCESS_DENIED);
return 0;
}
// For logged maps we still fake the file size, and leave it up to
// filesys to fill it. (see FSVolExtendFile)
dwFileLen = dwMapLen;
}
}
//
// Make sure the mapping doesn't already exist
//
EnterCriticalSection(&MapNameCS);
if (lpName) {
// Check name
len = strlenW(lpName);
if (len > MAX_PATH - 1) {
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
goto errexit;
}
EnterCriticalSection(&MapCS);
for (hMap = hMapList; hMap; hMap = lpm->hNext) {
lpm = HandleToMap(hMap);
if (lpm) {
if (lpm->name && !strcmpW(lpm->name->name, lpName)) {
// Found an existing map
IncRef(hMap, pCurProc);
LeaveCriticalSection(&MapCS);
if (hFile != INVALID_HANDLE_VALUE)
KernelCloseHandle(hFile);
KSetLastError(pCurThread, ERROR_ALREADY_EXISTS);
goto exit;
}
} else {
// No way to signal an error -- just continue
DEBUGCHK(0);
break;
}
}
KSetLastError(pCurThread, 0);
LeaveCriticalSection(&MapCS);
}
LeaveCriticalSection(&MapNameCS);
//
// Not found, validate params outside critsecs to avoid deadlocks
//
if ((hFile != INVALID_HANDLE_VALUE) && !bDirectROM) {
// Determine if paging is possible (Read/WriteFileWithSeek must be usable)
if (!ReadFileWithSeek(hFile, 0, 0, 0, 0, 0, 0)) {
SetFilePointer(hFile, 0, 0, 0);
if (dwFileLen && (!ReadFile(hFile, &testbyte, sizeof(BYTE), &len, 0)
|| (len != sizeof(BYTE)))) {
KernelCloseHandle(hFile);
KSetLastError(pCurThread, ERROR_INVALID_HANDLE);
return 0;
}
// Database volumes require paging
if (bNoAutoFlush) {
DEBUGMSG(1, (TEXT("Failing CreateMap on non-pageable file system\r\n")));
KernelCloseHandle(hFile);
KSetLastError(pCurThread, ERROR_NOT_SUPPORTED);
return 0;
}
bPage = FALSE;
}
// Verify that we can write to the file
if (dwFileLen && (flProtect == PAGE_READWRITE)) {
if ((bPage && (!ReadFileWithSeek(hFile, &testbyte, sizeof(BYTE), &len, 0, 0, 0)
|| (len != sizeof(BYTE))
|| !WriteFileWithSeek(hFile, &testbyte, sizeof(BYTE), &len, 0, 0, 0)
|| (len != sizeof(BYTE))))
|| (!bPage && (SetFilePointer(hFile, 0, 0, FILE_BEGIN)
|| !FSWriteFile(hFile, &testbyte, sizeof(BYTE), &len)
|| (len != sizeof(BYTE))))) {
KernelCloseHandle(hFile);
KSetLastError(pCurThread, ERROR_ACCESS_DENIED);
return 0;
}
}
if (!bPage) {
// Reserve memory for mapping
pData = FSMapMemReserve(PAGEALIGN_UP(dwMapLen), bNoAutoFlush);
if (!pData) {
if (hFile != INVALID_HANDLE_VALUE)
KernelCloseHandle(hFile);
KSetLastError(pCurThread, ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
// Commit
if (!FSMapMemCommit(pData, PAGEALIGN_UP(dwMapLen), PAGE_READWRITE)) {
FSMapMemFree(pData, PAGEALIGN_UP(dwMapLen), MEM_RELEASE);
if (hFile != INVALID_HANDLE_VALUE)
KernelCloseHandle(hFile);
KSetLastError(pCurThread, ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
// Copy the file data into the mapped memory
SetFilePointer(hFile, 0, 0, FILE_BEGIN);
if (!ReadFile(hFile, pData, dwMapLen, &len, 0) || (len != dwMapLen)) {
// Free up the memory we've grabbed
FSMapMemFree(pData, PAGEALIGN_UP(dwMapLen), MEM_DECOMMIT);
FSMapMemFree(pData, PAGEALIGN_UP(dwMapLen), MEM_RELEASE);
if (hFile != INVALID_HANDLE_VALUE)
KernelCloseHandle(hFile);
KSetLastError(pCurThread, ERROR_INVALID_HANDLE);
return 0;
}
// Mark the memory as R/O, if necessary
if (flProtect != PAGE_READWRITE)
VirtualProtect(pData, PAGEALIGN_UP(dwMapLen), PAGE_READONLY, &len);
}
}
//
// Check again to make sure the mapping doesn't already exist,
// since not holding critsecs above
//
EnterCriticalSection(&MapNameCS);
if (lpName) {
EnterCriticalSection(&MapCS);
for (hMap = hMapList; hMap; hMap = lpm->hNext) {
lpm = HandleToMap(hMap);
if (lpm) {
if (lpm->name && !strcmpW(lpm->name->name, lpName)) {
// Found an existing map
IncRef(hMap, pCurProc);
if (hFile != INVALID_HANDLE_VALUE)
KernelCloseHandle(hFile);
KSetLastError(pCurThread, ERROR_ALREADY_EXISTS);
LeaveCriticalSection(&MapCS);
if (!bPage && pData) {
// Free up the memory we've grabbed
FSMapMemFree(pData, PAGEALIGN_UP(dwMapLen), MEM_DECOMMIT);
FSMapMemFree(pData, PAGEALIGN_UP(dwMapLen), MEM_RELEASE);
}
goto exit;
}
} else {
// No way to signal an error -- just continue
DEBUGCHK(0);
break;
}
}
KSetLastError(pCurThread, 0);
LeaveCriticalSection(&MapCS);
}
//
// Prepare the map control struct
//
lpm = 0;
hMap = 0;
// Validate args -- Why do we do it here?
if (((flProtect != PAGE_READONLY) && (flProtect != PAGE_READWRITE))
|| dwMaxSizeHigh
|| ((hFile == INVALID_HANDLE_VALUE) && !dwMaxSizeLow)
|| ((flProtect == PAGE_READONLY) && (hFile == INVALID_HANDLE_VALUE))) {
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
goto errexit;
}
// Allocate space for the map struct
lpm = (LPFSMAP)AllocMem(HEAP_FSMAP);
if (!lpm) {
KSetLastError(pCurThread, ERROR_NOT_ENOUGH_MEMORY);
goto errexit;
}
lpm->pgqueue.idxHead = INVALID_PG_INDEX;
lpm->lpmlist = 0;
lpm->bNoAutoFlush = bNoAutoFlush;
lpm->bDirectROM = bDirectROM;
lpm->dwDirty = 0;
lpm->pBase = NULL;
// Copy the name
if (lpName) {
lpm->name = (Name *)AllocName((strlenW(lpName) + 1) * 2);
if (!lpm->name) {
KSetLastError(pCurThread, ERROR_NOT_ENOUGH_MEMORY);
goto errexit;
}
kstrcpyW(lpm->name->name, lpName);
} else
lpm->name = 0;
hMap = AllocHandle(&cinfMap, lpm, pCurProc);
if (!hMap) {
KSetLastError(pCurThread, ERROR_NOT_ENOUGH_MEMORY);
goto errexit;
}
lpm->length = dwMapLen;
lpm->reslen = PAGEALIGN_UP(lpm->length);
// Leave space for dirty bits
if ((flProtect == PAGE_READWRITE) && (hFile != INVALID_HANDLE_VALUE))
lpm->reslen += PAGEALIGN_UP(((lpm->reslen + PAGE_SIZE - 1) / PAGE_SIZE + 7) / 8); // one bit per page
if (!lpm->reslen)
lpm->reslen = PAGE_SIZE;
//
// If we haven't already reserved memory for mapping, do it now
//
if (bDirectROM) {
DWORD dwType, dwFileIndex, dwOffset;
LPBYTE lpPhys, lpVirt;
ROMFILE_FROM_OID(info.dwOID, dwType, dwFileIndex);
if (FindROMFile(dwType, dwFileIndex, &lpPhys, &dwFileLen)) {
// Round address down to page boundary
dwOffset = (DWORD)lpPhys & (PAGE_SIZE - 1);
lpPhys -= dwOffset;
dwMapLen = dwFileLen + dwOffset;
// Map location of the file in ROM into shared virtual address space
lpVirt = FSMapMemReserve (dwMapLen, FALSE);
if (!lpVirt) {
goto errexit;
}
if (!VirtualCopy(lpVirt, lpPhys, dwMapLen, PAGE_READONLY)) {
VirtualFree(lpVirt, 0, MEM_RELEASE); // Won't stomp lasterror
goto errexit;
}
lpm->pBase = lpVirt + dwOffset;
lpm->length = dwMapLen;
lpm->reslen = dwMapLen;
lpm->bRestart = 0;
lpm->pDirty = 0;
// lpVirt is recoverable for doing the free later
DEBUGCHK(lpVirt == (LPBYTE)PAGEALIGN_DOWN((DWORD)lpm->pBase));
} else {
// File info says the file is in ROM and uncompressed, but it wasn't found
DEBUGCHK(0);
KSetLastError(pCurThread, ERROR_FILE_NOT_FOUND);
goto errexit;
}
} else if (bPage) {
// Reserve memory for mapping
lpm->pBase = FSMapMemReserve(lpm->reslen, bNoAutoFlush);
if (!lpm->pBase) {
KSetLastError(pCurThread, ERROR_NOT_ENOUGH_MEMORY);
goto errexit;
}
// Commit
if ((flProtect == PAGE_READWRITE) && (hFile != INVALID_HANDLE_VALUE)) {
lpm->pDirty = lpm->pBase + PAGEALIGN_UP(lpm->length);
lpm->bRestart = 0;
if (!FSMapMemCommit(lpm->pDirty, lpm->reslen - PAGEALIGN_UP(lpm->length),
PAGE_READWRITE)) {
KSetLastError(pCurThread, ERROR_NOT_ENOUGH_MEMORY);
goto errexit;
}
} else
lpm->pDirty = 0;
} else {
// We already reserved memory, so fill in the struct
lpm->pBase = pData;
lpm->bRestart = 0;
lpm->pDirty = (flProtect == PAGE_READWRITE) ? (LPBYTE)1 : 0;
}
// Final sanity checks on the file
lpm->hFile = hFile;
if (hFile != INVALID_HANDLE_VALUE) {
PHDATA phd;
phd = HandleToPointer(hFile);
if ((phd->lock != 1) || (phd->ref.count != 1)) {
RETAILMSG(1, (L"CreateFileMapping called with handle not created with " \
L"CreateFileForMapping!\r\n"));
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
goto errexit;
}
lpm->filelen = dwFileLen;
if (lpm->filelen == 0xFFFFFFFF) {
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
goto errexit;
}
}
// Add to the list of mapped files
EnterCriticalSection(&MapCS);
lpm->hNext = hMapList;
hMapList = hMap;
LeaveCriticalSection(&MapCS);
exit:
LeaveCriticalSection(&MapNameCS);
if (bNoAutoFlush) {
if (!ValidateFile(lpm)) {
// We cannot commit the file. Fail.
goto errexitnocs;
}
}
DEBUGMSG(ZONE_ENTRY || ZONE_MAPFILE, (L"SC_Creat
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -