APIRET os2APIENTRY DosDupHandle(os2HFILE hFile, PHFILE pHfile) { int srcIdx = (int)hFile; FileTable.lock(srcIdx); if(!FileTable[srcIdx]) { FileTable.unlock(srcIdx); return 1; //FixMe } int dstIdx; if(*pHfile==(os2HFILE)-1) { dstIdx = FileTable.findAndLockFree(); if(dstIdx==-1) { FileTable.unlock(srcIdx); return 4; //too many open files } } else { dstIdx = (int)*pHfile; FileTable.lock(dstIdx); } if(srcIdx==dstIdx) { //no-op FileTable.unlock(srcIdx); return 0; } if(FileTable[dstIdx]) { CloseHandle(FileTable[dstIdx]->ntFileHandle); delete FileTable[dstIdx]; FileTable[dstIdx] = 0; } APIRET rc; HANDLE target; if(DuplicateHandle(GetCurrentProcess(), FileTable[srcIdx]->ntFileHandle, GetCurrentProcess(), &target, 0, TRUE, DUPLICATE_SAME_ACCESS )) { rc = 0; FileTable[dstIdx] = new ntFILE; FileTable[dstIdx]->ntFileHandle = target; FileTable[dstIdx]->mode = FileTable[srcIdx]->mode; if(dstIdx==0) SetStdHandle(STD_INPUT_HANDLE,target); else if(dstIdx==1) SetStdHandle(STD_OUTPUT_HANDLE,target); else if(dstIdx==2) SetStdHandle(STD_ERROR_HANDLE,target); } else rc = 6; //invalid handle FileTable.unlock(srcIdx); FileTable.unlock(dstIdx); return rc; }
APIRET os2APIENTRY DosQueryHType(os2HFILE hFile, PULONG pType, PULONG pAttr) { int idx=(int)hFile; FileTable.lock(idx); if(FileTable[idx]) { HANDLE hf=FileTable[idx]->ntFileHandle; FileTable.unlock(idx); DWORD t=GetFileType(hf); *pType = 0; switch(t) { case FILE_TYPE_DISK: *pType = 0; break; case FILE_TYPE_CHAR: *pType = 1; break; case FILE_TYPE_PIPE: *pType = 2; break; case FILE_TYPE_UNKNOWN: default: *pType = 3; } //We always set the network bit because we cannot retrieve device attributes *pType |= 0x80; *pAttr = 0; return 0; } else { FileTable.unlock(idx); return 6; //invalid handle } }
APIRET os2APIENTRY DosSetFHState(os2HFILE hFile, ULONG mode) { if(mode&0x077f) return 1; //FixMe: invalid flags APIRET rc; int idx=(int)hFile; FileTable.lock(idx); if(FileTable[idx]) { ULONG oldmode = FileTable[idx]->mode; ULONG newmode = (FileTable[idx]->mode&0x077f)|mode; if((oldmode&OPEN_FLAGS_NOINHERIT)!=(newmode&OPEN_FLAGS_NOINHERIT)) { //inheritance changed - duplicate and change HANDLE target; if(DuplicateHandle(GetCurrentProcess(), FileTable[idx]->ntFileHandle, GetCurrentProcess(), &target, 0, newmode&OPEN_FLAGS_NOINHERIT?FALSE:TRUE, DUPLICATE_SAME_ACCESS )) { CloseHandle(FileTable[idx]->ntFileHandle); FileTable[idx]->ntFileHandle = target; } else rc = (APIRET)GetLastError(); } else rc = 0; FileTable[idx]->mode = newmode; } else rc = 6; //invalid handle FileTable.unlock(idx); return rc; }
APIRET os2APIENTRY DosSetFilePtr(os2HFILE hFile, LONG ib, ULONG method, PULONG ibActual) { int idx=(int)hFile; FileTable.lock(idx); if(FileTable[idx]) { FileTable.unlock(idx); HANDLE hf=FileTable[idx]->ntFileHandle; DWORD dw = SetFilePointer(hf, (DWORD)ib, 0, (LONG)method ); if(dw==(DWORD)-1) return (APIRET)GetLastError(); else { *ibActual = (ULONG)dw; return 0; } } else { FileTable.unlock(idx); return 6; //invalid handle } }
APIRET os2APIENTRY DosSetFileInfo(os2HFILE hFile, ULONG ulInfoLevel, PVOID pInfoBuf, ULONG cbInfoBuf) { if(ulInfoLevel!=FIL_STANDARD && ulInfoLevel!=FIL_QUERYEASIZE) return 124; //invalid level APIRET rc; int idx=(int)hFile; FileTable.lock(idx); if(!FileTable[idx]) { rc = 6; //invalid handle goto done; } if(ulInfoLevel==FIL_STANDARD) { FILESTATUS3 *fs3=(FILESTATUS3*)pInfoBuf; FILETIME *lpftCreation=0; FILETIME ftCreation; FILETIME *lpftLastAccess=0; FILETIME ftLastAccess; FILETIME *lpftLastWrite=0; FILETIME ftLastWrite; if(cbInfoBuf>offsetof(FILESTATUS3,ftimeCreation) && (*(USHORT*)(&fs3->fdateCreation)!=0 || *(USHORT*)(&fs3->ftimeCreation)!=0)) { os22ntfiletime(fs3->fdateCreation,fs3->ftimeCreation,&ftCreation); lpftCreation=&ftCreation; } if(cbInfoBuf>offsetof(FILESTATUS3,ftimeLastAccess) && (*(USHORT*)(&fs3->fdateLastAccess)!=0 || *(USHORT*)(&fs3->ftimeLastAccess)!=0)) { os22ntfiletime(fs3->fdateLastAccess,fs3->ftimeCreation,&ftLastAccess); lpftLastAccess=&ftLastAccess; } if(cbInfoBuf>offsetof(FILESTATUS3,ftimeLastWrite) && (*(USHORT*)(&fs3->fdateLastWrite)!=0 || *(USHORT*)(&fs3->ftimeLastWrite)!=0)) { os22ntfiletime(fs3->fdateLastWrite,fs3->ftimeCreation,&ftLastWrite); lpftLastWrite=&ftLastWrite; } if(!SetFileTime(FileTable[idx]->ntFileHandle, lpftCreation, lpftLastAccess, lpftLastWrite )) { rc = (APIRET)GetLastError(); goto done; } //attributes cannot be changed rc = 0; } done: FileTable.unlock(idx); return rc; }
APIRET os2APIENTRY DosQueryFHState(os2HFILE hFile, PULONG pMode) { APIRET rc; int idx=(int)hFile; FileTable.lock(idx); if(FileTable[idx]) { rc = 0; *pMode = FileTable[idx]->mode; } else rc = 6; //invalid handle FileTable.unlock(idx); return rc; }
APIRET os2APIENTRY DosResetBuffer(os2HFILE hFile) { int idx=(int)hFile; FileTable.lock(idx); if(FileTable[idx]) { HANDLE hf=FileTable[idx]->ntFileHandle; FileTable.unlock(idx); if(FlushFileBuffers(hf)) return 0; else return (APIRET)GetLastError(); } else { FileTable.unlock(idx); return 6; //invalid handle } }
APIRET os2APIENTRY DosClose(os2HFILE hFile) { int idx=(int)hFile; FileTable.lock(idx); APIRET rc; if(FileTable[idx]) { CloseHandle(FileTable[idx]->ntFileHandle); delete FileTable[idx]; FileTable[idx] = 0; rc = 0; } else { rc = 6; //invalid handle } FileTable.unlock(idx); return rc; }
APIRET os2APIENTRY DosQueryFileInfo(os2HFILE hFile, ULONG ulInfoLevel, PVOID pInfo, ULONG cbInfoBuf) { if(ulInfoLevel!=FIL_STANDARD && ulInfoLevel!=FIL_QUERYEASIZE && ulInfoLevel!=FIL_QUERYEASFROMLIST) return 124; //invalid level APIRET rc; int idx=(int)hFile; FileTable.lock(idx); if(!FileTable[idx]) { rc = 6; //invalid handle goto done; } if(ulInfoLevel==FIL_QUERYEASFROMLIST) { rc = 254; //invalid EA name goto done; } BY_HANDLE_FILE_INFORMATION bhfi; if(!GetFileInformationByHandle(FileTable[idx]->ntFileHandle,&bhfi)) { rc = (APIRET)GetLastError(); goto done; } FILESTATUS4 *fs4; fs4=(FILESTATUS4 *)pInfo; if(cbInfoBuf>offsetof(FILESTATUS4,ftimeCreation)) ntfiletime2os2(bhfi.ftCreationTime, &fs4->fdateCreation, &fs4->ftimeCreation); if(cbInfoBuf>offsetof(FILESTATUS4,ftimeLastAccess)) ntfiletime2os2(bhfi.ftLastAccessTime, &fs4->fdateLastAccess, &fs4->ftimeLastAccess); if(cbInfoBuf>offsetof(FILESTATUS4,ftimeLastWrite)) ntfiletime2os2(bhfi.ftLastWriteTime, &fs4->fdateLastWrite, &fs4->ftimeLastWrite); if(cbInfoBuf>offsetof(FILESTATUS4,cbFile)) fs4->cbFile = (ULONG)bhfi.nFileSizeLow; if(cbInfoBuf>offsetof(FILESTATUS4,cbFileAlloc)) fs4->cbFileAlloc = (ULONG)bhfi.nFileSizeLow; if(cbInfoBuf>offsetof(FILESTATUS4,attrFile)) ntfileattr2os2(bhfi.dwFileAttributes, &fs4->attrFile); if(ulInfoLevel==FIL_QUERYEASIZE) fs4->cbList = 0; done: FileTable.unlock(idx); return rc; }
APIRET os2APIENTRY DosSetFileLocks(os2HFILE hFile, PFILELOCK pflUnlock, PFILELOCK pflLock, ULONG /*timeout*/, ULONG flags) { APIRET rc; int idx=(int)hFile; FileTable.lock(idx); if(FileTable[idx]) { rc=0; if(pflLock) { OVERLAPPED o; memset(&o,0,sizeof(o)); o.Offset = pflLock->lOffset; o.OffsetHigh = 0; if(!LockFileEx(FileTable[idx]->ntFileHandle, flags&1?0:LOCKFILE_EXCLUSIVE_LOCK, 0, pflLock->lRange, 0, 0 )) { rc = (APIRET)GetLastError(); } } if(rc==0 && pflUnlock) { if(!UnlockFile(FileTable[idx]->ntFileHandle, pflUnlock->lOffset, 0, pflUnlock->lRange, 0 )) { UnlockFile(FileTable[idx]->ntFileHandle, pflLock->lOffset,0, pflLock->lRange,0 ); rc = (APIRET)GetLastError(); } } } else rc = 6; //invalid handle FileTable.unlock(idx); return rc; }
APIRET os2APIENTRY DosSetFileSize(os2HFILE hFile, ULONG cbSize) { APIRET rc; int idx=(int)hFile; FileTable.lock(idx); if(FileTable[idx]) { APIRET rc; HANDLE hf=FileTable[idx]->ntFileHandle; DWORD current = SetFilePointer(hf,0,0,1); SetFilePointer(hf,(DWORD)cbSize,0,0); if(SetEndOfFile(hf)) rc = 0; else rc = (APIRET)GetLastError(); SetFilePointer(hf,current,0,0); } else { rc = 6; //invalid handle } FileTable.unlock(idx); return rc; }
APIRET os2APIENTRY DosWrite(os2HFILE hFile, PVOID pBuffer, ULONG cbWrite, PULONG pcbActual) { int idx=(int)hFile; FileTable.lock(idx); if(FileTable[idx]) { HANDLE hf=FileTable[idx]->ntFileHandle; FileTable.unlock(idx); if(WriteFile(hf, (LPVOID)pBuffer, (DWORD)cbWrite, (LPDWORD)pcbActual, 0 )) return 0; else return (APIRET)GetLastError(); } else { FileTable.unlock(idx); return 6; //invalid handle } }