找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 1546|回复: 1

编码技巧系列之一:抄代码的艺术

[复制链接]

857

主题

2632

回帖

2

精华

管理员

此生无悔入华夏,  长居日耳曼尼亚。  

积分
36130
发表于 2014-7-17 10:29:14 | 显示全部楼层 |阅读模式
最近需要把一个工程从用WIN32API转换到用NATIVE API实现,可惜我在把CreateFile变成NtCreateFile的时候卡壳了。不过我可没什么时间慢慢来调试,直接祭出“屌爆绝招”之一:抄代码。

说起抄代码,其实这事我也做了不少了,不过以前都是抄所谓大牛的代码,抄了还被人喷(其实我心里想:抄你代码是看得起你)。而这次,我直接抄一个国外开源工程的代码:ReactOS。ReactOS是一个山寨操作系统,它的历史什么的我就不讲了,只说它的官网是www.reactos.org,感兴趣的请自己去看。

下面贴出我修改好的山寨版CreateFileW,加上NTDLL.LIB和NTDLL.H可以直接使用:
  1. HANDLE MyCreateFileW
  2. (
  3.         LPCTSTR lpFileName,
  4.         DWORD dwDesiredAccess,
  5.         DWORD dwShareMode,
  6.         LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  7.         DWORD dwCreationDisposition,
  8.         DWORD dwFlagsAndAttributes,
  9.         HANDLE hTemplateFile
  10. )
  11. {

  12.         PVOID BaseAddr;
  13.         OBJECT_ATTRIBUTES ObjectAttributes;
  14.         IO_STATUS_BLOCK IoStatusBlock;
  15.         UNICODE_STRING NtPathU;
  16.         HANDLE FileHandle;
  17.         NTSTATUS Status;
  18.         ULONG FileAttributes, Flags = 0;
  19.         PVOID EaBuffer = NULL;
  20.         ULONG EaLength = 0;

  21.         if (!lpFileName || !lpFileName[0])
  22.         {
  23.                 SetLastError( ERROR_PATH_NOT_FOUND );
  24.                 return INVALID_HANDLE_VALUE;
  25.         }

  26.         //TRACE("CreateFileW(lpFileName %S)\n",lpFileName);
  27.         //MessageBoxW(0,lpFileName,0,0);

  28.         /* validate & translate the creation disposition */
  29.         switch (dwCreationDisposition)
  30.         {
  31.         case CREATE_NEW:
  32.                 dwCreationDisposition = FILE_CREATE;
  33.                 break;

  34.         case CREATE_ALWAYS:
  35.                 dwCreationDisposition = FILE_OVERWRITE_IF;
  36.                 break;

  37.         case OPEN_EXISTING:
  38.                 dwCreationDisposition = FILE_OPEN;
  39.                 break;

  40.         case OPEN_ALWAYS:
  41.                 dwCreationDisposition = FILE_OPEN_IF;
  42.                 break;

  43.         case TRUNCATE_EXISTING:
  44.                 dwCreationDisposition = FILE_OVERWRITE;
  45.                 break;

  46.         default:
  47.                 SetLastError(ERROR_INVALID_PARAMETER);
  48.                 return (INVALID_HANDLE_VALUE);
  49.         }

  50.         /* validate & translate the flags */

  51.         /* translate the flags that need no validation */
  52.         if (!(dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
  53.         {
  54.                 /* yes, nonalert is correct! apc's are not delivered
  55.                 while waiting for file io to complete */
  56.                 Flags |= FILE_SYNCHRONOUS_IO_NONALERT;
  57.         }

  58.         if(dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH)
  59.                 Flags |= FILE_WRITE_THROUGH;

  60.         if(dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING)
  61.                 Flags |= FILE_NO_INTERMEDIATE_BUFFERING;

  62.         if(dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS)
  63.                 Flags |= FILE_RANDOM_ACCESS;

  64.         if(dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN)
  65.                 Flags |= FILE_SEQUENTIAL_ONLY;

  66.         if(dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE)
  67.                 Flags |= FILE_DELETE_ON_CLOSE;

  68.         if(dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS)
  69.         {
  70.                 if(dwDesiredAccess & GENERIC_ALL)
  71.                         Flags |= FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REMOTE_INSTANCE;
  72.                 else
  73.                 {
  74.                         if(dwDesiredAccess & GENERIC_READ)
  75.                                 Flags |= FILE_OPEN_FOR_BACKUP_INTENT;

  76.                         if(dwDesiredAccess & GENERIC_WRITE)
  77.                                 Flags |= FILE_OPEN_REMOTE_INSTANCE;
  78.                 }
  79.         }
  80.         else
  81.                 Flags |= FILE_NON_DIRECTORY_FILE;

  82.         if(dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT)
  83.                 Flags |= FILE_OPEN_REPARSE_POINT;

  84.         if(dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL)
  85.                 Flags |= FILE_OPEN_NO_RECALL;

  86.         FileAttributes = (dwFlagsAndAttributes & (FILE_ATTRIBUTE_VALID_FLAGS & ~FILE_ATTRIBUTE_DIRECTORY));

  87.         /* handle may allways be waited on and querying attributes are allways allowed */
  88.         dwDesiredAccess |= SYNCHRONIZE | FILE_READ_ATTRIBUTES;

  89.         /* FILE_FLAG_POSIX_SEMANTICS is handled later */

  90.         /* validate & translate the filename */
  91.         if (!RtlDosPathNameToNtPathName_U ((PWSTR)lpFileName,
  92.                 &NtPathU,
  93.                 NULL,
  94.                 NULL))
  95.         {
  96.                 //MessageBoxA(0,"Invalid path\n",0,0);
  97.                 SetLastError(ERROR_FILE_NOT_FOUND);
  98.                 return INVALID_HANDLE_VALUE;
  99.         }

  100.         //MessageBoxW(0,NtPathU.Buffer,0,0);
  101.         //TRACE("NtPathU \'%wZ\'\n", &NtPathU);


  102.         if (hTemplateFile != NULL)
  103.         {
  104.                 FILE_EA_INFORMATION EaInformation;

  105.                 for (;;)
  106.                 {
  107.                         /* try to get the size of the extended attributes, if we fail just continue
  108.                         creating the file without copying the attributes! */
  109.                         Status = NtQueryInformationFile(hTemplateFile,
  110.                                 &IoStatusBlock,
  111.                                 &EaInformation,
  112.                                 sizeof(FILE_EA_INFORMATION),
  113.                                 FileEaInformation);
  114.                         if (NT_SUCCESS(Status) && (EaInformation.EaSize != 0))
  115.                         {
  116.                                 /* there's extended attributes to read, let's give it a try */
  117.                                 /*EaBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
  118.                                 0,
  119.                                 EaInformation.EaSize);*/
  120.                                 EaBuffer = malloc(EaInformation.EaSize);

  121.                                 if (EaBuffer == NULL)
  122.                                 {
  123.                                         /*RtlFreeHeap(RtlGetProcessHeap(),
  124.                                         0,
  125.                                         NtPathU.Buffer);*/
  126.                                         BaseAddr=NtPathU.Buffer;
  127.                                         RtlFreeUnicodeString(&NtPathU);

  128.                                         /* the template file handle is valid and has extended attributes,
  129.                                         however we seem to lack some memory here. We should fail here! */
  130.                                         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  131.                                         return INVALID_HANDLE_VALUE;
  132.                                 }

  133.                                 Status = NtQueryEaFile(hTemplateFile,
  134.                                         &IoStatusBlock,
  135.                                         EaBuffer,
  136.                                         EaInformation.EaSize,
  137.                                         FALSE,
  138.                                         NULL,
  139.                                         0,
  140.                                         NULL,
  141.                                         TRUE);

  142.                                 if (NT_SUCCESS(Status))
  143.                                 {
  144.                                         /* we successfully read the extended attributes, break the loop
  145.                                         and continue */
  146.                                         EaLength = EaInformation.EaSize;
  147.                                         break;
  148.                                 }
  149.                                 else
  150.                                 {
  151.                                         /*RtlFreeHeap(RtlGetProcessHeap(),
  152.                                         0,
  153.                                         EaBuffer);*/
  154.                                         free(EaBuffer);
  155.                                         EaBuffer = NULL;

  156.                                         if (Status != STATUS_BUFFER_TOO_SMALL)
  157.                                         {
  158.                                                 /* unless we just allocated not enough memory, break the loop
  159.                                                 and just continue without copying extended attributes */
  160.                                                 break;
  161.                                         }
  162.                                 }
  163.                         }
  164.                         else
  165.                         {
  166.                                 /* we either failed to get the size of the extended attributes or
  167.                                 they're empty, just continue as there's no need to copy
  168.                                 attributes */
  169.                                 break;
  170.                         }
  171.                 }
  172.         }

  173.         /* build the object attributes */
  174.         InitializeObjectAttributes(&ObjectAttributes,
  175.                 &NtPathU,
  176.                 0,
  177.                 NULL,
  178.                 NULL);

  179.         if (lpSecurityAttributes)
  180.         {
  181.                 if(lpSecurityAttributes->bInheritHandle)
  182.                         ObjectAttributes.Attributes |= OBJ_INHERIT;

  183.                 ObjectAttributes.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
  184.         }

  185.         if(!(dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS))
  186.                 ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;

  187.         /* perform the call */
  188.         Status = NtCreateFile (&FileHandle,
  189.                 dwDesiredAccess,
  190.                 &ObjectAttributes,
  191.                 &IoStatusBlock,
  192.                 NULL,
  193.                 FileAttributes,
  194.                 dwShareMode,
  195.                 dwCreationDisposition,
  196.                 Flags,
  197.                 EaBuffer,
  198.                 EaLength);

  199.         //RtlFreeHeap(RtlGetProcessHeap(),
  200.         //            0,
  201.         //            NtPathU.Buffer);
  202.         BaseAddr=NtPathU.Buffer;
  203.         RtlFreeUnicodeString(&NtPathU);

  204.         /* free the extended attributes buffer if allocated */
  205.         if (EaBuffer != NULL)
  206.         {
  207.                 //RtlFreeHeap(RtlGetProcessHeap(),
  208.                 //            0,
  209.                 //            EaBuffer);
  210.                 BaseAddr=EaBuffer;
  211.                 free(EaBuffer);
  212.         }

  213.         /* error */
  214.         if (!NT_SUCCESS(Status))
  215.         {
  216.                 /* In the case file creation was rejected due to CREATE_NEW flag
  217.                 * was specified and file with that name already exists, correct
  218.                 * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS.
  219.                 * Note: RtlNtStatusToDosError is not the subject to blame here.
  220.                 */
  221.                 if (Status == STATUS_OBJECT_NAME_COLLISION &&
  222.                         dwCreationDisposition == FILE_CREATE)
  223.                 {
  224.                         SetLastError( ERROR_FILE_EXISTS );
  225.                 }
  226.                 else
  227.                 {
  228.                         //BaseSetLastNTError (Status);
  229.                         SetLastError(RtlNtStatusToDosError(Status));
  230.                 }

  231.                 return INVALID_HANDLE_VALUE;
  232.         }

  233.         /*
  234.         create with OPEN_ALWAYS (FILE_OPEN_IF) returns info = FILE_OPENED or FILE_CREATED
  235.         create with CREATE_ALWAYS (FILE_OVERWRITE_IF) returns info = FILE_OVERWRITTEN or FILE_CREATED
  236.         */
  237.         if (dwCreationDisposition == FILE_OPEN_IF)
  238.         {
  239.                 SetLastError(IoStatusBlock.Information == FILE_OPENED ? ERROR_ALREADY_EXISTS : ERROR_SUCCESS);
  240.         }
  241.         else if (dwCreationDisposition == FILE_OVERWRITE_IF)
  242.         {
  243.                 SetLastError(IoStatusBlock.Information == FILE_OVERWRITTEN ? ERROR_ALREADY_EXISTS : ERROR_SUCCESS);
  244.         }
  245.         else
  246.         {
  247.                 SetLastError(ERROR_SUCCESS);
  248.         }

  249.         return FileHandle;
  250. }
复制代码

0

主题

18

回帖

0

精华

铂金会员

积分
2252
发表于 2014-7-17 13:56:55 | 显示全部楼层
能抄当然抄了{:soso_e113:}
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表