NTSTATUS PvfsCcbQueryFileBasicInformation( PPVFS_CCB pCcb, PFILE_BASIC_INFORMATION pFileInfo ) { NTSTATUS ntError = STATUS_SUCCESS; PVFS_STAT Stat = {0}; PVFS_FILE_NAME baseObjectFileName = { 0 }; if (PvfsIsDefaultStream(pCcb->pScb)) { ntError = PvfsGetFileAttributes(pCcb, &pFileInfo->FileAttributes); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSysFstat(pCcb->fd, &Stat); BAIL_ON_NT_STATUS(ntError); } else { // Named Streams share meta-data with the owning FCB ntError = PvfsBuildFileNameFromCString( &baseObjectFileName, pCcb->pScb->pOwnerFcb->pszFilename, 0); BAIL_ON_NT_STATUS(ntError); ntError = PvfsGetFilenameAttributes( PvfsGetCStringBaseFileName(&baseObjectFileName), &pFileInfo->FileAttributes); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSysStatByFileName(&baseObjectFileName, &Stat); BAIL_ON_NT_STATUS(ntError); } ntError = PvfsUnixToWinTime(&pFileInfo->LastAccessTime, Stat.s_atime); BAIL_ON_NT_STATUS(ntError); ntError = PvfsUnixToWinTime(&pFileInfo->LastWriteTime, Stat.s_mtime); BAIL_ON_NT_STATUS(ntError); ntError = PvfsUnixToWinTime(&pFileInfo->ChangeTime, Stat.s_ctime); BAIL_ON_NT_STATUS(ntError); ntError = PvfsUnixToWinTime(&pFileInfo->CreationTime, Stat.s_crtime); BAIL_ON_NT_STATUS(ntError); error: PvfsDestroyFileName(&baseObjectFileName); return ntError; }
NTSTATUS PvfsCheckDeleteOnClose( IN IRP_ARGS_CREATE CreateArgs, IN PSTR pszFilename, IN ACCESS_MASK GrantedAccess ) { NTSTATUS ntError = STATUS_SUCCESS; FILE_ATTRIBUTES Attributes = 0; if (!(CreateArgs.CreateOptions & FILE_DELETE_ON_CLOSE)) { goto cleanup; } if (!(GrantedAccess & DELETE)) { ntError = STATUS_ACCESS_DENIED; BAIL_ON_NT_STATUS(ntError); } /* ReadOnly is largely ignored by the file system on directories. It is used by the Windows explorer.exe to mark folders as "special" */ if (CreateArgs.CreateOptions & FILE_DIRECTORY_FILE) { ntError = STATUS_SUCCESS; goto cleanup; } /* Dealing with files from here down */ if (pszFilename) { ntError = PvfsGetFilenameAttributes( pszFilename, &Attributes); BAIL_ON_NT_STATUS(ntError); } switch (CreateArgs.CreateDisposition) { case FILE_OPEN: case FILE_OPEN_IF: case FILE_SUPERSEDE: case FILE_CREATE: if (pszFilename) { if (Attributes & FILE_ATTRIBUTE_READONLY) { ntError = STATUS_CANNOT_DELETE; BAIL_ON_NT_STATUS(ntError); } } else { if (CreateArgs.FileAttributes & FILE_ATTRIBUTE_READONLY) { ntError = STATUS_CANNOT_DELETE; BAIL_ON_NT_STATUS(ntError); } } break; case FILE_OVERWRITE: case FILE_OVERWRITE_IF: if (pszFilename && (CreateArgs.FileAttributes == 0)) { if (Attributes & FILE_ATTRIBUTE_READONLY) { ntError = STATUS_CANNOT_DELETE; BAIL_ON_NT_STATUS(ntError); } } else { if (CreateArgs.FileAttributes & FILE_ATTRIBUTE_READONLY) { ntError = STATUS_CANNOT_DELETE; BAIL_ON_NT_STATUS(ntError); } } break; } ntError = STATUS_SUCCESS; cleanup: return ntError; error: goto cleanup; }
static NTSTATUS FillFileIdFullDirInfoBuffer( PVOID pBuffer, DWORD dwBufLen, PSTR pszParent, PPVFS_DIRECTORY_ENTRY pEntry, PDWORD pdwConsumed ) { NTSTATUS ntError = STATUS_UNSUCCESSFUL; PFILE_ID_FULL_DIR_INFORMATION pFileInfo = (PFILE_ID_FULL_DIR_INFORMATION)pBuffer; PWSTR pwszFilename = NULL; PSTR pszFullPath = NULL; DWORD dwNeeded = 0; size_t W16FilenameLen = 0; size_t W16FilenameLenBytes = 0; /* Check for enough space for static members */ if (dwBufLen < sizeof(*pFileInfo)) { ntError = STATUS_BUFFER_TOO_SMALL; BAIL_ON_NT_STATUS(ntError); } /* Build the absolute path and stat() it */ ntError = RtlCStringAllocatePrintf( &pszFullPath, "%s/%s", pszParent, pEntry->pszFilename); BAIL_ON_NT_STATUS(ntError); ntError = PvfsSysStat(pszFullPath, &pEntry->Stat); BAIL_ON_NT_STATUS(ntError); ntError = RtlWC16StringAllocateFromCString( &pwszFilename, pEntry->pszFilename); BAIL_ON_NT_STATUS(ntError); ntError = FillFileIdFullDirInfoStatic( pFileInfo, pwszFilename, &pEntry->Stat); BAIL_ON_NT_STATUS(ntError); /* We have more information here to fill in the file attributes */ ntError = PvfsGetFilenameAttributes( pszFullPath, &pFileInfo->FileAttributes); BAIL_ON_NT_STATUS(ntError); /* Save what we have used so far */ *pdwConsumed = sizeof(*pFileInfo); /* Calculate space */ W16FilenameLen = RtlWC16StringNumChars(pwszFilename); W16FilenameLenBytes = W16FilenameLen * sizeof(WCHAR); dwNeeded = sizeof(*pFileInfo) + W16FilenameLenBytes; /* alignment on 8 byte boundary */ if (dwNeeded % 8) { dwNeeded += 8 - (dwNeeded % 8); } if (dwNeeded > dwBufLen) { ntError = STATUS_BUFFER_TOO_SMALL; BAIL_ON_NT_STATUS(ntError); } pFileInfo->FileNameLength = W16FilenameLenBytes; memcpy(pFileInfo->FileName, pwszFilename, W16FilenameLenBytes); *pdwConsumed = dwNeeded; ntError = STATUS_SUCCESS; cleanup: RtlCStringFree(&pszFullPath); RtlWC16StringFree(&pwszFilename); return ntError; error: goto cleanup; }