编码技巧系列之一:抄代码的艺术
最近需要把一个工程从用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)
{
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;
} 能抄当然抄了{:soso_e113:}
页:
[1]