|
最近需要把一个工程从用WIN32API转换到用NATIVE API实现,可惜我在把CreateFile变成NtCreateFile的时候卡壳了。不过我可没什么时间慢慢来调试,直接祭出“屌爆绝招”之一:抄代码。
说起抄代码,其实这事我也做了不少了,不过以前都是抄所谓大牛的代码,抄了还被人喷(其实我心里想:抄你代码是看得起你)。而这次,我直接抄一个国外开源工程的代码:ReactOS。ReactOS是一个山寨操作系统,它的历史什么的我就不讲了,只说它的官网是www.reactos.org,感兴趣的请自己去看。
下面贴出我修改好的山寨版CreateFileW,加上NTDLL.LIB和NTDLL.H可以直接使用:
- HANDLE MyCreateFileW
- (
- LPCTSTR lpFileName,
- DWORD dwDesiredAccess,
- DWORD dwShareMode,
- LPSECURITY_ATTRIBUTES lpSecurityAttributes,
- DWORD dwCreationDisposition,
- DWORD dwFlagsAndAttributes,
- HANDLE hTemplateFile
- )
- {
- PVOID BaseAddr;
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- UNICODE_STRING NtPathU;
- HANDLE FileHandle;
- NTSTATUS Status;
- ULONG FileAttributes, Flags = 0;
- PVOID EaBuffer = NULL;
- ULONG EaLength = 0;
- if (!lpFileName || !lpFileName[0])
- {
- SetLastError( ERROR_PATH_NOT_FOUND );
- return INVALID_HANDLE_VALUE;
- }
- //TRACE("CreateFileW(lpFileName %S)\n",lpFileName);
- //MessageBoxW(0,lpFileName,0,0);
- /* validate & translate the creation disposition */
- switch (dwCreationDisposition)
- {
- case CREATE_NEW:
- dwCreationDisposition = FILE_CREATE;
- break;
- case CREATE_ALWAYS:
- dwCreationDisposition = FILE_OVERWRITE_IF;
- break;
- case OPEN_EXISTING:
- dwCreationDisposition = FILE_OPEN;
- break;
- case OPEN_ALWAYS:
- dwCreationDisposition = FILE_OPEN_IF;
- break;
- case TRUNCATE_EXISTING:
- dwCreationDisposition = FILE_OVERWRITE;
- break;
- default:
- SetLastError(ERROR_INVALID_PARAMETER);
- return (INVALID_HANDLE_VALUE);
- }
- /* validate & translate the flags */
- /* translate the flags that need no validation */
- if (!(dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
- {
- /* yes, nonalert is correct! apc's are not delivered
- while waiting for file io to complete */
- Flags |= FILE_SYNCHRONOUS_IO_NONALERT;
- }
- if(dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH)
- Flags |= FILE_WRITE_THROUGH;
- if(dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING)
- Flags |= FILE_NO_INTERMEDIATE_BUFFERING;
- if(dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS)
- Flags |= FILE_RANDOM_ACCESS;
- if(dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN)
- Flags |= FILE_SEQUENTIAL_ONLY;
- if(dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE)
- Flags |= FILE_DELETE_ON_CLOSE;
- if(dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS)
- {
- if(dwDesiredAccess & GENERIC_ALL)
- Flags |= FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REMOTE_INSTANCE;
- else
- {
- if(dwDesiredAccess & GENERIC_READ)
- Flags |= FILE_OPEN_FOR_BACKUP_INTENT;
- if(dwDesiredAccess & GENERIC_WRITE)
- Flags |= FILE_OPEN_REMOTE_INSTANCE;
- }
- }
- else
- Flags |= FILE_NON_DIRECTORY_FILE;
- if(dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT)
- Flags |= FILE_OPEN_REPARSE_POINT;
- if(dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL)
- Flags |= FILE_OPEN_NO_RECALL;
- FileAttributes = (dwFlagsAndAttributes & (FILE_ATTRIBUTE_VALID_FLAGS & ~FILE_ATTRIBUTE_DIRECTORY));
- /* handle may allways be waited on and querying attributes are allways allowed */
- dwDesiredAccess |= SYNCHRONIZE | FILE_READ_ATTRIBUTES;
- /* FILE_FLAG_POSIX_SEMANTICS is handled later */
- /* validate & translate the filename */
- if (!RtlDosPathNameToNtPathName_U ((PWSTR)lpFileName,
- &NtPathU,
- NULL,
- NULL))
- {
- //MessageBoxA(0,"Invalid path\n",0,0);
- SetLastError(ERROR_FILE_NOT_FOUND);
- return INVALID_HANDLE_VALUE;
- }
- //MessageBoxW(0,NtPathU.Buffer,0,0);
- //TRACE("NtPathU \'%wZ\'\n", &NtPathU);
- if (hTemplateFile != NULL)
- {
- FILE_EA_INFORMATION EaInformation;
- for (;;)
- {
- /* try to get the size of the extended attributes, if we fail just continue
- creating the file without copying the attributes! */
- Status = NtQueryInformationFile(hTemplateFile,
- &IoStatusBlock,
- &EaInformation,
- sizeof(FILE_EA_INFORMATION),
- FileEaInformation);
- if (NT_SUCCESS(Status) && (EaInformation.EaSize != 0))
- {
- /* there's extended attributes to read, let's give it a try */
- /*EaBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
- 0,
- EaInformation.EaSize);*/
- EaBuffer = malloc(EaInformation.EaSize);
- if (EaBuffer == NULL)
- {
- /*RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- NtPathU.Buffer);*/
- BaseAddr=NtPathU.Buffer;
- RtlFreeUnicodeString(&NtPathU);
-
- /* the template file handle is valid and has extended attributes,
- however we seem to lack some memory here. We should fail here! */
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return INVALID_HANDLE_VALUE;
- }
- Status = NtQueryEaFile(hTemplateFile,
- &IoStatusBlock,
- EaBuffer,
- EaInformation.EaSize,
- FALSE,
- NULL,
- 0,
- NULL,
- TRUE);
- if (NT_SUCCESS(Status))
- {
- /* we successfully read the extended attributes, break the loop
- and continue */
- EaLength = EaInformation.EaSize;
- break;
- }
- else
- {
- /*RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- EaBuffer);*/
- free(EaBuffer);
- EaBuffer = NULL;
- if (Status != STATUS_BUFFER_TOO_SMALL)
- {
- /* unless we just allocated not enough memory, break the loop
- and just continue without copying extended attributes */
- break;
- }
- }
- }
- else
- {
- /* we either failed to get the size of the extended attributes or
- they're empty, just continue as there's no need to copy
- attributes */
- break;
- }
- }
- }
- /* build the object attributes */
- InitializeObjectAttributes(&ObjectAttributes,
- &NtPathU,
- 0,
- NULL,
- NULL);
- if (lpSecurityAttributes)
- {
- if(lpSecurityAttributes->bInheritHandle)
- ObjectAttributes.Attributes |= OBJ_INHERIT;
- ObjectAttributes.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
- }
- if(!(dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS))
- ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
- /* perform the call */
- Status = NtCreateFile (&FileHandle,
- dwDesiredAccess,
- &ObjectAttributes,
- &IoStatusBlock,
- NULL,
- FileAttributes,
- dwShareMode,
- dwCreationDisposition,
- Flags,
- EaBuffer,
- EaLength);
- //RtlFreeHeap(RtlGetProcessHeap(),
- // 0,
- // NtPathU.Buffer);
- BaseAddr=NtPathU.Buffer;
- RtlFreeUnicodeString(&NtPathU);
-
- /* free the extended attributes buffer if allocated */
- if (EaBuffer != NULL)
- {
- //RtlFreeHeap(RtlGetProcessHeap(),
- // 0,
- // EaBuffer);
- BaseAddr=EaBuffer;
- free(EaBuffer);
- }
- /* error */
- if (!NT_SUCCESS(Status))
- {
- /* In the case file creation was rejected due to CREATE_NEW flag
- * was specified and file with that name already exists, correct
- * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS.
- * Note: RtlNtStatusToDosError is not the subject to blame here.
- */
- if (Status == STATUS_OBJECT_NAME_COLLISION &&
- dwCreationDisposition == FILE_CREATE)
- {
- SetLastError( ERROR_FILE_EXISTS );
- }
- else
- {
- //BaseSetLastNTError (Status);
- SetLastError(RtlNtStatusToDosError(Status));
- }
- return INVALID_HANDLE_VALUE;
- }
- /*
- create with OPEN_ALWAYS (FILE_OPEN_IF) returns info = FILE_OPENED or FILE_CREATED
- create with CREATE_ALWAYS (FILE_OVERWRITE_IF) returns info = FILE_OVERWRITTEN or FILE_CREATED
- */
- if (dwCreationDisposition == FILE_OPEN_IF)
- {
- SetLastError(IoStatusBlock.Information == FILE_OPENED ? ERROR_ALREADY_EXISTS : ERROR_SUCCESS);
- }
- else if (dwCreationDisposition == FILE_OVERWRITE_IF)
- {
- SetLastError(IoStatusBlock.Information == FILE_OVERWRITTEN ? ERROR_ALREADY_EXISTS : ERROR_SUCCESS);
- }
- else
- {
- SetLastError(ERROR_SUCCESS);
- }
- return FileHandle;
- }
复制代码 |
|