⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mapfile.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    
    // 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 + -