bool SetFileSize64(LPCTSTR lpszFilename, __int64 llSize) { HANDLE hFile=CreateFile(lpszFilename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return false; if (SetFilePointer64(hFile, llSize, FILE_BEGIN) == -1) { CloseHandle(hFile); return false; } if (!SetEndOfFile(hFile)) { CloseHandle(hFile); return false; } if (!CloseHandle(hFile)) return false; return true; }
EFI_STATUS EmuBlockIoOpenDevice ( IN EMU_BLOCK_IO_PRIVATE *Private ) { EFI_STATUS Status; UINT64 FileSize; struct statfs buf; // // If the device is already opened, close it // if (Private->fd >= 0) { EmuBlockIoReset (&Private->EmuBlockIo, FALSE); } // // Open the device // Private->fd = open (Private->Filename, Private->Mode, 0644); if (Private->fd < 0) { printf ("EmuOpenBlock: Could not open %s: %s\n", Private->Filename, strerror(errno)); Private->Media->MediaPresent = FALSE; Status = EFI_NO_MEDIA; goto Done; } if (!Private->Media->MediaPresent) { // // BugBug: try to emulate if a CD appears - notify drivers to check it out // Private->Media->MediaPresent = TRUE; } // // get the size of the file // Status = SetFilePointer64 (Private, 0, &FileSize, SEEK_END); if (EFI_ERROR (Status)) { printf ("EmuOpenBlock: Could not get filesize of %s\n", Private->Filename); Status = EFI_UNSUPPORTED; goto Done; } if (FileSize == 0) { // lseek fails on a real device. ioctl calls are OS specific #if __APPLE__ { UINT32 BlockSize; if (ioctl (Private->fd, DKIOCGETBLOCKSIZE, &BlockSize) == 0) { Private->Media->BlockSize = BlockSize; } if (ioctl (Private->fd, DKIOCGETBLOCKCOUNT, &Private->NumberOfBlocks) == 0) { if ((Private->NumberOfBlocks == 0) && (BlockSize == 0x800)) { // A DVD is ~ 4.37 GB so make up a number Private->Media->LastBlock = (0x100000000ULL/0x800) - 1; } else { Private->Media->LastBlock = Private->NumberOfBlocks - 1; } } ioctl (Private->fd, DKIOCGETMAXBLOCKCOUNTWRITE, &Private->Media->OptimalTransferLengthGranularity); } #else { size_t BlockSize; UINT64 DiskSize; if (ioctl (Private->fd, BLKSSZGET, &BlockSize) == 0) { Private->Media->BlockSize = BlockSize; } if (ioctl (Private->fd, BLKGETSIZE64, &DiskSize) == 0) { Private->NumberOfBlocks = DivU64x32 (DiskSize, (UINT32)BlockSize); Private->Media->LastBlock = Private->NumberOfBlocks - 1; } } #endif } else { Private->Media->BlockSize = Private->BlockSize; Private->NumberOfBlocks = DivU64x32 (FileSize, Private->Media->BlockSize); Private->Media->LastBlock = Private->NumberOfBlocks - 1; if (fstatfs (Private->fd, &buf) == 0) { #if __APPLE__ Private->Media->OptimalTransferLengthGranularity = buf.f_iosize/buf.f_bsize; #else Private->Media->OptimalTransferLengthGranularity = buf.f_bsize/buf.f_bsize; #endif } } DEBUG ((EFI_D_INIT, "%HEmuOpenBlock: opened %a%N\n", Private->Filename)); Status = EFI_SUCCESS; Done: if (EFI_ERROR (Status)) { if (Private->fd >= 0) { EmuBlockIoReset (&Private->EmuBlockIo, FALSE); } } return Status; }
EFI_STATUS EmuBlockIoReadWriteCommon ( IN EMU_BLOCK_IO_PRIVATE *Private, IN UINT32 MediaId, IN EFI_LBA Lba, IN UINTN BufferSize, IN VOID *Buffer, IN CHAR8 *CallerName ) { EFI_STATUS Status; UINTN BlockSize; UINT64 LastBlock; INT64 DistanceToMove; UINT64 DistanceMoved; if (Private->fd < 0) { Status = EmuBlockIoOpenDevice (Private); if (EFI_ERROR (Status)) { return Status; } } if (!Private->Media->MediaPresent) { DEBUG ((EFI_D_INIT, "%s: No Media\n", CallerName)); return EFI_NO_MEDIA; } if (Private->Media->MediaId != MediaId) { return EFI_MEDIA_CHANGED; } if ((UINTN) Buffer % Private->Media->IoAlign != 0) { return EFI_INVALID_PARAMETER; } // // Verify buffer size // BlockSize = Private->Media->BlockSize; if (BufferSize == 0) { DEBUG ((EFI_D_INIT, "%s: Zero length read\n", CallerName)); return EFI_SUCCESS; } if ((BufferSize % BlockSize) != 0) { DEBUG ((EFI_D_INIT, "%s: Invalid read size\n", CallerName)); return EFI_BAD_BUFFER_SIZE; } LastBlock = Lba + (BufferSize / BlockSize) - 1; if (LastBlock > Private->Media->LastBlock) { DEBUG ((EFI_D_INIT, "ReadBlocks: Attempted to read off end of device\n")); return EFI_INVALID_PARAMETER; } // // Seek to End of File // DistanceToMove = MultU64x32 (Lba, BlockSize); Status = SetFilePointer64 (Private, DistanceToMove, &DistanceMoved, SEEK_SET); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_INIT, "WriteBlocks: SetFilePointer failed\n")); return EmuBlockIoError (Private); } return EFI_SUCCESS; }
int CSimpleFileStream::Seek(__int64 pos) { SetFilePointer64(m_fileHandle, pos + m_offset); return 1; }
DWORD CTag_OpenDML::FindJUNK_LISTINFO(HANDLE hFile,__int64 llFileSize) { DWORD dwMax = 0; DWORD dwJunkSize = 0; FOURCC id; FOURCC fType; DWORD dwRet; DWORD dwSize; // 1G = 1073741824 // 2G = 2147483648 // 4G = 4294967296 while(1) { __int64 llChunkHead = SetFilePointer64(hFile,0,FILE_CURRENT); if(llChunkHead >= llFileSize) { if(dwJunkSize) { if(dwMax < dwJunkSize) { dwMax = dwJunkSize; } dwJunkSize = 0; } break; } if(!ReadFile(hFile,&id,sizeof(id),&dwRet,NULL) || (dwRet != sizeof(id))) { SetFilePointer64(hFile,llChunkHead,FILE_BEGIN); return FALSE; } if(!ReadFile(hFile,&dwSize,sizeof(dwSize),&dwRet,NULL) || (dwRet != sizeof(dwSize))) { SetFilePointer64(hFile,llChunkHead,FILE_BEGIN); return FALSE; } if(dwSize%2) { dwSize++; } switch(id){ case FOURCC_RIFF: if(dwJunkSize) { if(dwMax < dwJunkSize) { dwMax = dwJunkSize; } dwJunkSize = 0; } break; case FOURCC_LIST: if(!ReadFile(hFile,&fType,sizeof(fType),&dwRet,NULL) || (dwRet != sizeof(fType))) { SetFilePointer64(hFile,llChunkHead,FILE_BEGIN); return FALSE; } if(fType == mmioFOURCC('I','N','F','O')) { dwJunkSize += dwSize + 8; } else { if(dwJunkSize) { if(dwMax < dwJunkSize) { dwMax = dwJunkSize; } dwJunkSize = 0; } } dwSize -= 4; break; default: if(id == mmioFOURCC('J','U','N','K')) { dwJunkSize += dwSize + 8; } else { if(dwJunkSize) { if(dwMax < dwJunkSize) { dwMax = dwJunkSize; } dwJunkSize = 0; } } break; } TRACE(_T("%c%c%c%c %c%c%c%c %I64u(%lu)\n"), (((char *)(&id))[0]),(((char *)(&id))[1]),(((char *)(&id))[2]),(((char *)(&id))[3]), (((char *)(&fType))[0]),(((char *)(&fType))[1]),(((char *)(&fType))[2]),(((char *)(&fType))[3]), llChunkHead,dwSize ); SetFilePointer64(hFile,(__int64 )dwSize,FILE_CURRENT); } return dwMax; }
/* ret: -1 = 更新失敗 -2 = Avi2のため更新できず(avi2でriff-avixの書き換えは未実装なため) */ DWORD CTag_OpenDML::Save(LPCTSTR szFileName) { DWORD dwWin32errorCode = ERROR_SUCCESS; HANDLE hFile; DWORD dwRet; // LONG lAddressHeight; DWORD dwRiffAviSize; __int64 llFileSize; __int64 llLastJUNKPtr; DWORD dwLastJUNKSize; __int64 llLargeJUNKPtr; DWORD dwLargeJunkSize; DWORD dwInfoSize; FOURCC id,type; BOOL bFindJUNK; DWORD dwSize; __int64 llOffset; FieldMap::iterator p; //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //ファイルを開く hFile = CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ,NULL, OPEN_EXISTING, //ファイルを開きます。指定したファイルが存在していない場合、この関数は失敗します。 FILE_ATTRIBUTE_NORMAL, NULL); if(hFile == INVALID_HANDLE_VALUE) { dwWin32errorCode = GetLastError(); goto exit; } llFileSize = GetFileSize64(hFile); //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //RIFF-AVI を確認 if(!ReadFile(hFile,&id,sizeof(id),&dwRet,NULL)) { dwWin32errorCode = GetLastError(); goto exit; } // 総サイズ if(!ReadFile(hFile,&dwRiffAviSize,sizeof(dwRiffAviSize),&dwRet,NULL)) { dwWin32errorCode = GetLastError(); goto exit; } // (念のため) if((dwRiffAviSize+8) > llFileSize) { dwRiffAviSize = (llFileSize & 0x000000007fffffff) - 8; if(dwRiffAviSize <= 0) { goto exit; } } // Riff type if(!ReadFile(hFile,&type,sizeof(type),&dwRet,NULL)) { dwWin32errorCode = GetLastError(); goto exit; } if((FOURCC_RIFF != id) && (m_type != type)) { dwWin32errorCode = GetLastError(); goto exit; } //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // LIST-INFOを押し込めるスペースを計算 dwLargeJunkSize = FindJUNK_LISTINFO(hFile,(__int64 )dwRiffAviSize); TRACE(_T("FindJUNK_LISTINFO=%d\n"),dwLargeJunkSize); // 付加するLIST-INFOのサイズを計算 dwInfoSize = GetInfoChunkSize(); dwInfoSize += 12; if((dwLargeJunkSize < (dwInfoSize+8/*JUNK____*/)) && !(dwLargeJunkSize == dwInfoSize) ) { // LIST-INFOを終端に追加可能か? //先頭チャンクに戻る SetFilePointer64(hFile,0,FILE_BEGIN); if(FindChunk(hFile,llFileSize,MMIO_FINDRIFF,mmioFOURCC('A','V','I','X'),&dwSize)) { // AVIXが後に続く場合はファイルの作り直しが必要 return Save_1(hFile); } } //先頭チャンクに戻る(すべてのLIST-INFOを処理) SetFilePointer64(hFile,12,FILE_BEGIN); while(1) { //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //LIST-INFOを検索(見つからないときはRiff論理終端に移動) if(FindChunk(hFile,dwRiffAviSize + 8,MMIO_FINDLIST,mmioFOURCC('I','N','F','O'),&dwSize)) { // (チャンクの先頭+8にいる) llOffset = SetFilePointer64(hFile,0,FILE_CURRENT); if((llOffset + dwSize) < llFileSize) { //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //LIST-INFOが最後尾に付いていないときは、現存LIST-INFOをJUNKに置換する SetFilePointer64(hFile,-12,FILE_CURRENT); id = mmioFOURCC('J','U','N','K'); WriteFile(hFile,&id,sizeof(id),&dwRet,NULL); //先頭チャンクに戻る(すべてのLIST-INFOを処理) SetFilePointer64(hFile,12,FILE_BEGIN); continue; } else { //LIST-INFOの先頭に移動 SetFilePointer64(hFile,-12,FILE_CURRENT); //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //LIST-INFOを削除 SetEndOfFile(hFile); dwRiffAviSize = (DWORD)(llOffset - 12 - 8); //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //RIFF-AVI チャンクサイズを修正 SetFilePointer(hFile,4,NULL,FILE_BEGIN); WriteFile(hFile,&dwRiffAviSize,sizeof(dwRiffAviSize),&dwRet,NULL); SetFilePointer64(hFile,dwRiffAviSize+8,FILE_BEGIN); } } break; } if(dwInfoSize == 12) { // 保存するデータはなし goto exit; } //先頭チャンクに戻る(すべてのLIST-INFOを処理) SetFilePointer64(hFile,12,FILE_BEGIN); bFindJUNK = FALSE; dwLastJUNKSize = 0; dwLargeJunkSize = 0; while(1) { //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // JUNKを統合 if(FindChunk(hFile,llFileSize,MMIO_FINDCHUNK,mmioFOURCC('J','U','N','K'),&dwSize)) { // (チャンクの先頭+8にいる) if(bFindJUNK) { __int64 llNowPtr = SetFilePointer64(hFile,0,FILE_CURRENT) - 8; // 直前のJUNKと統合可能か? if(llNowPtr == (llLastJUNKPtr + dwLastJUNKSize)) { // 統合 SetFilePointer64(hFile,llLastJUNKPtr+4,FILE_BEGIN); dwLastJUNKSize += dwSize + 8; dwSize = dwLastJUNKSize - 8; WriteFile(hFile,&dwSize,sizeof(dwSize),&dwRet,NULL); for(DWORD i=0; i<dwSize; i++) { if((DWORD)m_strJunkHeader.GetLength() > i) { char c = (char)m_strJunkHeader[i]; // QQQ ANSI文字のみ対応 WriteFile(hFile,&c,1,&dwRet,NULL); } else { WriteFile(hFile,"",1,&dwRet,NULL); } } } else { SetFilePointer64(hFile,dwSize,FILE_CURRENT); bFindJUNK = FALSE; } } else { bFindJUNK = TRUE; llLastJUNKPtr = SetFilePointer64(hFile,0,FILE_CURRENT) - 8; dwLastJUNKSize = dwSize + 8; SetFilePointer64(hFile,dwSize,FILE_CURRENT); } if(dwLargeJunkSize < dwLastJUNKSize) { llLargeJUNKPtr = llLastJUNKPtr; dwLargeJunkSize = dwLastJUNKSize; } continue; } break; } // LIST-INFOがJUNKの中に収まるか計算 if((dwLargeJunkSize < (dwInfoSize+8/*JUNK____*/)) && !(dwLargeJunkSize == dwInfoSize) ) { // (収まらない) // LIST-INFOを終端に追加 llLargeJUNKPtr = dwRiffAviSize+8; //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //RIFF-AVI チャンクサイズを修正 dwRiffAviSize += dwInfoSize; SetFilePointer(hFile,4,NULL,FILE_BEGIN); WriteFile(hFile,&dwRiffAviSize,sizeof(dwRiffAviSize),&dwRet,NULL); } //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //LIST-INFOを書き込む SetFilePointer64(hFile,llLargeJUNKPtr,FILE_BEGIN); dwSize = dwInfoSize - 8; id = FOURCC_LIST; type = mmioFOURCC('I','N','F','O'); WriteFile(hFile,&id,sizeof(id),&dwRet,NULL); WriteFile(hFile,&dwSize,sizeof(dwSize),&dwRet,NULL); WriteFile(hFile,&type,sizeof(type),&dwRet,NULL); //全てのフィールド情報を保存 p = m_fields.begin(); while(p != m_fields.end()) { FOURCC id = p->first; CString *pStr = &p->second; DWORD len; char *str = TstrToBytesAlloc(*pStr, -1, (int*)&len, BTC_CODE_ANSI); if(str) { if(len > 1) { WriteFile(hFile,&id,sizeof(id),&dwRet,NULL); WriteFile(hFile,&len,sizeof(len),&dwRet,NULL); WriteFile(hFile,str,len,&dwRet,NULL); if(len%2) { WriteFile(hFile,"\x00",1,&dwRet,NULL); } } free(str); } p++; } ////////////////////////////////////// // 残りスペースをJUNKで埋める TRACE(_T("dwLargeJunkSize=%d\n"),dwLargeJunkSize); TRACE(_T("dwInfoSize=%d\n"),dwInfoSize); if(dwLargeJunkSize >= (dwInfoSize+8/*JUNK____*/)) { dwSize = dwLargeJunkSize-dwInfoSize-8; id = mmioFOURCC('J','U','N','K'); WriteFile(hFile,&id,sizeof(id),&dwRet,NULL); WriteFile(hFile,&dwSize,sizeof(dwSize),&dwRet,NULL); TRACE(_T("Start dwSize=%d\n"),dwSize); for(DWORD i=0; i<dwSize; i++) { if((DWORD)m_strJunkHeader.GetLength() > i) { char c = (char)m_strJunkHeader[i]; // QQQ ANSI文字のみ対応 WriteFile(hFile,&c,1,&dwRet,NULL); } else { WriteFile(hFile,"",1,&dwRet,NULL); } } TRACE(_T("End dwSize=%d\n"),dwSize); } exit: if(hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); } return dwWin32errorCode; }
//チャンクを検索します //return=TRUEのときは見つかったチャンクの先頭+8の位置にいます //return=FALSEのときは最終チャンクの最後尾+1 BOOL CTag_OpenDML::FindChunk(HANDLE hFile,__int64 llFileSize,UINT flag,FOURCC type,DWORD *pdwSize) { FOURCC id; FOURCC fType; DWORD dwRet; DWORD dwSize; // 1G = 1073741824 // 2G = 2147483648 // 4G = 4294967296 while(1) { __int64 llChunkHead = SetFilePointer64(hFile,0,FILE_CURRENT); if(llChunkHead >= llFileSize) { break; } if(!ReadFile(hFile,&id,sizeof(id),&dwRet,NULL) || (dwRet != sizeof(id))) { SetFilePointer64(hFile,llChunkHead,FILE_BEGIN); return FALSE; } if(!ReadFile(hFile,&dwSize,sizeof(dwSize),&dwRet,NULL) || (dwRet != sizeof(dwSize))) { SetFilePointer64(hFile,llChunkHead,FILE_BEGIN); return FALSE; } if(dwSize%2) { dwSize++; } *pdwSize = dwSize; switch(id){ case FOURCC_RIFF: if(!ReadFile(hFile,&fType,sizeof(fType),&dwRet,NULL) || (dwRet != sizeof(fType))) { SetFilePointer64(hFile,llChunkHead,FILE_BEGIN); return FALSE; } *pdwSize -= sizeof(fType); if(flag != MMIO_FINDRIFF) { break; } if(fType == type) { // pdwSizeの補正(ありえない値を返さないように) __int64 ptr = llChunkHead + 12; if((llFileSize - ptr) < *pdwSize) { *pdwSize = (DWORD)(llFileSize - ptr); } return TRUE; } break; case FOURCC_LIST: if(!ReadFile(hFile,&fType,sizeof(fType),&dwRet,NULL) || (dwRet != sizeof(fType))) { SetFilePointer64(hFile,llChunkHead,FILE_BEGIN); return FALSE; } *pdwSize -= sizeof(fType); if(flag != MMIO_FINDLIST) { break; } if(fType == type) { // pdwSizeの補正(ありえない値を返さないように) __int64 ptr = llChunkHead + 12; if((llFileSize - ptr) < *pdwSize) { *pdwSize = (DWORD)(llFileSize - ptr); } return TRUE; } break; default: fType = 0x20202020; if(id == type) { // pdwSizeの補正(ありえない値を返さないように) __int64 ptr = llChunkHead + 8; if((llFileSize - ptr) < *pdwSize) { *pdwSize = (DWORD)(llFileSize - ptr); } return TRUE; } break; } TRACE(_T("%c%c%c%c %c%c%c%c %I64u(%lu)\n"), (((char *)(&id))[0]),(((char *)(&id))[1]),(((char *)(&id))[2]),(((char *)(&id))[3]), (((char *)(&fType))[0]),(((char *)(&fType))[1]),(((char *)(&fType))[2]),(((char *)(&fType))[3]), llChunkHead,dwSize ); SetFilePointer64(hFile,(__int64 )*pdwSize,FILE_CURRENT); } return FALSE; }
__int64 GetFilePointer64(HANDLE hFile) { return SetFilePointer64(hFile, 0, FILE_CURRENT); }