Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4816 lines
127 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Support routines for NT-native binaries.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "pch.hpp"
  9. #ifdef NT_NATIVE
  10. #define _CRTIMP
  11. #include <time.h>
  12. #include <ntddser.h>
  13. #include "ntnative.h"
  14. #include "cmnutil.hpp"
  15. void* __cdecl operator new(size_t Bytes)
  16. {
  17. return RtlAllocateHeap(RtlProcessHeap(), 0, Bytes);
  18. }
  19. void __cdecl operator delete(void* Ptr)
  20. {
  21. RtlFreeHeap(RtlProcessHeap(), 0, Ptr);
  22. }
  23. int __cdecl _purecall(void)
  24. {
  25. return 0;
  26. }
  27. int __cdecl atexit(void (__cdecl* func)(void))
  28. {
  29. return 1;
  30. }
  31. #define BASE_YEAR_ADJUSTMENT 11644473600
  32. time_t __cdecl time(time_t* timer)
  33. {
  34. LARGE_INTEGER SystemTime;
  35. //
  36. // Read system time from shared region.
  37. //
  38. do
  39. {
  40. SystemTime.HighPart = USER_SHARED_DATA->SystemTime.High1Time;
  41. SystemTime.LowPart = USER_SHARED_DATA->SystemTime.LowPart;
  42. } while (SystemTime.HighPart != USER_SHARED_DATA->SystemTime.High2Time);
  43. // Convert to seconds.
  44. ULONG64 TimeDate = SystemTime.QuadPart / 10000000;
  45. // Convert from base year 1601 to base year 1970.
  46. return (ULONG)(TimeDate - BASE_YEAR_ADJUSTMENT);
  47. }
  48. #ifdef _X86_
  49. LONG WINAPI
  50. InterlockedIncrement(
  51. IN OUT LONG volatile *lpAddend
  52. )
  53. {
  54. __asm
  55. {
  56. mov ecx,lpAddend ; get pointer to addend variable
  57. mov eax,1 ; set increment value
  58. lock xadd [ecx],eax ; interlocked increment
  59. inc eax ; adjust return value
  60. }
  61. }
  62. LONG WINAPI
  63. InterlockedDecrement(
  64. IN OUT LONG volatile *lpAddend
  65. )
  66. {
  67. __asm
  68. {
  69. mov ecx,lpAddend ; get pointer to addend variable
  70. mov eax,-1 ; set decrement value
  71. lock xadd [ecx],eax ; interlocked decrement
  72. dec eax ; adjust return value
  73. }
  74. }
  75. LONG WINAPI
  76. InterlockedExchange(
  77. IN OUT LONG volatile *Target,
  78. IN LONG Value
  79. )
  80. {
  81. __asm
  82. {
  83. mov ecx, [Target] ; (ecx) = Target
  84. mov edx, [Value] ; (edx) = Value
  85. mov eax, [ecx] ; get comperand value
  86. Ixchg:
  87. lock cmpxchg [ecx], edx ; compare and swap
  88. jnz Ixchg ; if nz, exchange failed
  89. }
  90. }
  91. #endif // #ifdef _X86_
  92. DWORD WINAPI
  93. GetLastError(
  94. VOID
  95. )
  96. {
  97. return (DWORD)NtCurrentTeb()->LastErrorValue;
  98. }
  99. VOID WINAPI
  100. SetLastError(
  101. DWORD dwErrCode
  102. )
  103. {
  104. NtCurrentTeb()->LastErrorValue = (LONG)dwErrCode;
  105. }
  106. void
  107. BaseSetLastNTError(NTSTATUS NtStatus)
  108. {
  109. SetLastError(RtlNtStatusToDosError(NtStatus));
  110. }
  111. void WINAPI
  112. Sleep(DWORD Milliseconds)
  113. {
  114. LARGE_INTEGER Timeout;
  115. Win32ToNtTimeout(Milliseconds, &Timeout);
  116. NtDelayExecution(FALSE, &Timeout);
  117. }
  118. HANDLE WINAPI
  119. OpenProcess(
  120. DWORD dwDesiredAccess,
  121. BOOL bInheritHandle,
  122. DWORD dwProcessId
  123. )
  124. {
  125. NTSTATUS Status;
  126. OBJECT_ATTRIBUTES Obja;
  127. HANDLE Handle=NULL;
  128. CLIENT_ID ClientId;
  129. ClientId.UniqueThread = NULL;
  130. ClientId.UniqueProcess = LongToHandle(dwProcessId);
  131. InitializeObjectAttributes(
  132. &Obja,
  133. NULL,
  134. (bInheritHandle ? OBJ_INHERIT : 0),
  135. NULL,
  136. NULL
  137. );
  138. Status = NtOpenProcess(
  139. &Handle,
  140. (ACCESS_MASK)dwDesiredAccess,
  141. &Obja,
  142. &ClientId
  143. );
  144. if ( NT_SUCCESS(Status) )
  145. {
  146. BaseSetLastNTError(Status);
  147. return Handle;
  148. }
  149. else
  150. {
  151. return NULL;
  152. }
  153. }
  154. BOOL
  155. CloseHandle(
  156. HANDLE hObject
  157. )
  158. {
  159. return NT_SUCCESS(NtClose(hObject));
  160. }
  161. int
  162. WINAPI
  163. MultiByteToWideChar(
  164. IN UINT CodePage,
  165. IN DWORD dwFlags,
  166. IN LPCSTR lpMultiByteStr,
  167. IN int cbMultiByte,
  168. OUT LPWSTR lpWideCharStr,
  169. IN int cchWideChar)
  170. {
  171. if (CodePage != CP_ACP || dwFlags != 0)
  172. {
  173. return 0;
  174. }
  175. UNICODE_STRING Wide;
  176. ANSI_STRING Ansi;
  177. RtlInitAnsiString(&Ansi, lpMultiByteStr);
  178. Wide.Buffer = lpWideCharStr;
  179. Wide.MaximumLength = (USHORT)cchWideChar;
  180. if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&Wide, &Ansi, FALSE)))
  181. {
  182. return 0;
  183. }
  184. else
  185. {
  186. return Wide.Length / sizeof(WCHAR) + 1;
  187. }
  188. }
  189. int
  190. WINAPI
  191. WideCharToMultiByte(
  192. IN UINT CodePage,
  193. IN DWORD dwFlags,
  194. IN LPCWSTR lpWideCharStr,
  195. IN int cchWideChar,
  196. OUT LPSTR lpMultiByteStr,
  197. IN int cbMultiByte,
  198. IN LPCSTR lpDefaultChar,
  199. OUT LPBOOL lpUsedDefaultChar)
  200. {
  201. if (CodePage != CP_ACP || dwFlags != 0 || lpDefaultChar != NULL ||
  202. lpUsedDefaultChar != NULL)
  203. {
  204. return 0;
  205. }
  206. UNICODE_STRING Wide;
  207. ANSI_STRING Ansi;
  208. RtlInitUnicodeString(&Wide, lpWideCharStr);
  209. Ansi.Buffer = lpMultiByteStr;
  210. Ansi.MaximumLength = (USHORT)cbMultiByte;
  211. if (!NT_SUCCESS(RtlUnicodeStringToAnsiString(&Ansi, &Wide, FALSE)))
  212. {
  213. return 0;
  214. }
  215. else
  216. {
  217. return Ansi.Length + 1;
  218. }
  219. }
  220. DWORD
  221. WINAPI
  222. SuspendThread(
  223. IN HANDLE hThread
  224. )
  225. {
  226. DWORD PrevCount=0;
  227. NTSTATUS NtStatus;
  228. NtStatus = NtSuspendThread(hThread, &PrevCount);
  229. if (NT_SUCCESS(NtStatus))
  230. {
  231. return PrevCount;
  232. }
  233. else
  234. {
  235. BaseSetLastNTError(NtStatus);
  236. return -1;
  237. }
  238. }
  239. DWORD
  240. WINAPI
  241. ResumeThread(
  242. IN HANDLE hThread
  243. )
  244. {
  245. DWORD PrevCount=0;
  246. NTSTATUS NtStatus;
  247. NtStatus = NtResumeThread(hThread, &PrevCount);
  248. if (NT_SUCCESS(NtStatus))
  249. {
  250. return PrevCount;
  251. }
  252. else
  253. {
  254. BaseSetLastNTError(NtStatus);
  255. return -1;
  256. }
  257. }
  258. DWORD
  259. WINAPI
  260. GetCurrentThreadId(void)
  261. {
  262. return HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread);
  263. }
  264. DWORD
  265. WINAPI
  266. GetCurrentProcessId(void)
  267. {
  268. return HandleToUlong(NtCurrentTeb()->ClientId.UniqueProcess);
  269. }
  270. HANDLE
  271. WINAPI
  272. GetCurrentProcess(void)
  273. {
  274. return NtCurrentProcess();
  275. }
  276. BOOL
  277. WINAPI
  278. ReadProcessMemory(
  279. HANDLE hProcess,
  280. LPCVOID lpBaseAddress,
  281. LPVOID lpBuffer,
  282. SIZE_T nSize,
  283. SIZE_T *lpNumberOfBytesRead
  284. )
  285. {
  286. NTSTATUS Status;
  287. SIZE_T NtNumberOfBytesRead=0;
  288. Status = NtReadVirtualMemory(hProcess,
  289. (PVOID)lpBaseAddress,
  290. lpBuffer,
  291. nSize,
  292. &NtNumberOfBytesRead
  293. );
  294. if ( lpNumberOfBytesRead != NULL )
  295. {
  296. *lpNumberOfBytesRead = NtNumberOfBytesRead;
  297. }
  298. if ( !NT_SUCCESS(Status) )
  299. {
  300. BaseSetLastNTError(Status);
  301. return FALSE;
  302. }
  303. else
  304. {
  305. return TRUE;
  306. }
  307. }
  308. BOOL
  309. WINAPI
  310. WriteProcessMemory(
  311. HANDLE hProcess,
  312. LPVOID lpBaseAddress,
  313. LPCVOID lpBuffer,
  314. SIZE_T nSize,
  315. SIZE_T *lpNumberOfBytesWritten
  316. )
  317. {
  318. NTSTATUS Status, xStatus;
  319. ULONG OldProtect;
  320. SIZE_T RegionSize;
  321. PVOID Base;
  322. SIZE_T NtNumberOfBytesWritten;
  323. //
  324. // Set the protection to allow writes
  325. //
  326. RegionSize = nSize;
  327. Base = lpBaseAddress;
  328. Status = NtProtectVirtualMemory(hProcess,
  329. &Base,
  330. &RegionSize,
  331. PAGE_EXECUTE_READWRITE,
  332. &OldProtect
  333. );
  334. if ( NT_SUCCESS(Status) )
  335. {
  336. //
  337. // See if previous protection was writable. If so,
  338. // then reset protection and do the write.
  339. // Otherwise, see if previous protection was read-only or
  340. // no access. In this case, don't do the write, just fail
  341. //
  342. if ( (OldProtect & PAGE_READWRITE) == PAGE_READWRITE ||
  343. (OldProtect & PAGE_WRITECOPY) == PAGE_WRITECOPY ||
  344. (OldProtect & PAGE_EXECUTE_READWRITE) == PAGE_EXECUTE_READWRITE ||
  345. (OldProtect & PAGE_EXECUTE_WRITECOPY) == PAGE_EXECUTE_WRITECOPY )
  346. {
  347. Status = NtProtectVirtualMemory(hProcess,
  348. &Base,
  349. &RegionSize,
  350. OldProtect,
  351. &OldProtect
  352. );
  353. Status = NtWriteVirtualMemory(hProcess,
  354. lpBaseAddress,
  355. lpBuffer,
  356. nSize,
  357. &NtNumberOfBytesWritten
  358. );
  359. if ( lpNumberOfBytesWritten != NULL )
  360. {
  361. *lpNumberOfBytesWritten = NtNumberOfBytesWritten;
  362. }
  363. if ( !NT_SUCCESS(Status) )
  364. {
  365. BaseSetLastNTError(Status);
  366. return FALSE;
  367. }
  368. NtFlushInstructionCache(hProcess,lpBaseAddress,nSize);
  369. return TRUE;
  370. }
  371. else
  372. {
  373. //
  374. // See if the previous protection was read only or no access. If
  375. // this is the case, restore the previous protection and return
  376. // an access violation error.
  377. //
  378. if ( (OldProtect & PAGE_NOACCESS) == PAGE_NOACCESS ||
  379. (OldProtect & PAGE_READONLY) == PAGE_READONLY )
  380. {
  381. Status = NtProtectVirtualMemory(hProcess,
  382. &Base,
  383. &RegionSize,
  384. OldProtect,
  385. &OldProtect
  386. );
  387. BaseSetLastNTError(STATUS_ACCESS_VIOLATION);
  388. return FALSE;
  389. }
  390. else
  391. {
  392. //
  393. // The previous protection must have been code and the caller
  394. // is trying to set a breakpoint or edit the code. Do the write
  395. // and then restore the previous protection.
  396. //
  397. Status = NtWriteVirtualMemory(hProcess,
  398. lpBaseAddress,
  399. lpBuffer,
  400. nSize,
  401. &NtNumberOfBytesWritten
  402. );
  403. if ( lpNumberOfBytesWritten != NULL )
  404. {
  405. *lpNumberOfBytesWritten = NtNumberOfBytesWritten;
  406. }
  407. xStatus = NtProtectVirtualMemory(hProcess,
  408. &Base,
  409. &RegionSize,
  410. OldProtect,
  411. &OldProtect
  412. );
  413. if ( !NT_SUCCESS(Status) )
  414. {
  415. BaseSetLastNTError(STATUS_ACCESS_VIOLATION);
  416. return STATUS_ACCESS_VIOLATION;
  417. }
  418. NtFlushInstructionCache(hProcess,lpBaseAddress,nSize);
  419. return TRUE;
  420. }
  421. }
  422. }
  423. else
  424. {
  425. BaseSetLastNTError(Status);
  426. return FALSE;
  427. }
  428. }
  429. BOOL
  430. DuplicateHandle(
  431. HANDLE hSourceProcessHandle,
  432. HANDLE hSourceHandle,
  433. HANDLE hTargetProcessHandle,
  434. LPHANDLE lpTargetHandle,
  435. DWORD dwDesiredAccess,
  436. BOOL bInheritHandle,
  437. DWORD dwOptions
  438. )
  439. {
  440. NTSTATUS Status;
  441. Status = NtDuplicateObject(hSourceProcessHandle,
  442. hSourceHandle,
  443. hTargetProcessHandle,
  444. lpTargetHandle,
  445. (ACCESS_MASK)dwDesiredAccess,
  446. bInheritHandle ? OBJ_INHERIT : 0,
  447. dwOptions
  448. );
  449. if ( NT_SUCCESS(Status) )
  450. {
  451. return TRUE;
  452. }
  453. else
  454. {
  455. BaseSetLastNTError(Status);
  456. return FALSE;
  457. }
  458. return FALSE;
  459. }
  460. BOOL
  461. APIENTRY
  462. GetThreadContext(
  463. HANDLE hThread,
  464. LPCONTEXT lpContext
  465. )
  466. {
  467. NTSTATUS Status;
  468. Status = NtGetContextThread(hThread,lpContext);
  469. if ( !NT_SUCCESS(Status) )
  470. {
  471. BaseSetLastNTError(Status);
  472. return FALSE;
  473. }
  474. else
  475. {
  476. return TRUE;
  477. }
  478. }
  479. BOOL
  480. APIENTRY
  481. SetThreadContext(
  482. HANDLE hThread,
  483. CONST CONTEXT *lpContext
  484. )
  485. {
  486. NTSTATUS Status;
  487. Status = NtSetContextThread(hThread,(PCONTEXT)lpContext);
  488. if ( !NT_SUCCESS(Status) )
  489. {
  490. BaseSetLastNTError(Status);
  491. return FALSE;
  492. }
  493. else
  494. {
  495. return TRUE;
  496. }
  497. }
  498. BOOL
  499. APIENTRY
  500. GetThreadSelectorEntry(
  501. HANDLE hThread,
  502. DWORD dwSelector,
  503. LPLDT_ENTRY lpSelectorEntry
  504. )
  505. {
  506. #if defined(i386)
  507. DESCRIPTOR_TABLE_ENTRY DescriptorEntry;
  508. NTSTATUS Status;
  509. DescriptorEntry.Selector = dwSelector;
  510. Status = NtQueryInformationThread(hThread,
  511. ThreadDescriptorTableEntry,
  512. &DescriptorEntry,
  513. sizeof(DescriptorEntry),
  514. NULL
  515. );
  516. if ( !NT_SUCCESS(Status) )
  517. {
  518. BaseSetLastNTError(Status);
  519. return FALSE;
  520. }
  521. *lpSelectorEntry = DescriptorEntry.Descriptor;
  522. return TRUE;
  523. #else
  524. BaseSetLastNTError(STATUS_NOT_SUPPORTED);
  525. return FALSE;
  526. #endif // i386
  527. }
  528. BOOL
  529. WINAPI
  530. SetEnvironmentVariableA(
  531. LPCSTR lpName,
  532. LPCSTR lpValue
  533. )
  534. {
  535. NTSTATUS Status;
  536. STRING Name;
  537. STRING Value;
  538. UNICODE_STRING UnicodeName;
  539. UNICODE_STRING UnicodeValue;
  540. RtlInitString( &Name, lpName );
  541. Status = RtlAnsiStringToUnicodeString(&UnicodeName, &Name, TRUE);
  542. if ( !NT_SUCCESS(Status) )
  543. {
  544. BaseSetLastNTError( Status );
  545. return FALSE;
  546. }
  547. if (ARGUMENT_PRESENT( lpValue ))
  548. {
  549. RtlInitString( &Value, lpValue );
  550. Status = RtlAnsiStringToUnicodeString(&UnicodeValue, &Value, TRUE);
  551. if ( !NT_SUCCESS(Status) )
  552. {
  553. BaseSetLastNTError( Status );
  554. RtlFreeUnicodeString(&UnicodeName);
  555. return FALSE;
  556. }
  557. Status = RtlSetEnvironmentVariable( NULL, &UnicodeName, &UnicodeValue);
  558. RtlFreeUnicodeString(&UnicodeValue);
  559. }
  560. else
  561. {
  562. Status = RtlSetEnvironmentVariable( NULL, &UnicodeName, NULL);
  563. }
  564. RtlFreeUnicodeString(&UnicodeName);
  565. if (NT_SUCCESS( Status ))
  566. {
  567. return( TRUE );
  568. }
  569. else
  570. {
  571. BaseSetLastNTError( Status );
  572. return( FALSE );
  573. }
  574. }
  575. BOOL
  576. WINAPI
  577. TerminateProcess(
  578. HANDLE hProcess,
  579. UINT uExitCode
  580. )
  581. {
  582. NTSTATUS Status;
  583. if ( hProcess == NULL )
  584. {
  585. SetLastError(ERROR_INVALID_HANDLE);
  586. return FALSE;
  587. }
  588. Status = NtTerminateProcess(hProcess,(NTSTATUS)uExitCode);
  589. if ( NT_SUCCESS(Status) )
  590. {
  591. return TRUE;
  592. }
  593. else
  594. {
  595. BaseSetLastNTError(Status);
  596. return FALSE;
  597. }
  598. }
  599. BOOL
  600. WINAPI
  601. GetExitCodeProcess(
  602. HANDLE hProcess,
  603. LPDWORD lpExitCode
  604. )
  605. {
  606. NTSTATUS Status;
  607. PROCESS_BASIC_INFORMATION BasicInformation;
  608. Status = NtQueryInformationProcess(hProcess,
  609. ProcessBasicInformation,
  610. &BasicInformation,
  611. sizeof(BasicInformation),
  612. NULL
  613. );
  614. if ( NT_SUCCESS(Status) )
  615. {
  616. *lpExitCode = BasicInformation.ExitStatus;
  617. return TRUE;
  618. }
  619. else
  620. {
  621. BaseSetLastNTError(Status);
  622. return FALSE;
  623. }
  624. }
  625. HANDLE
  626. WINAPI
  627. NtNativeCreateFileW(
  628. LPCWSTR lpFileName,
  629. DWORD dwDesiredAccess,
  630. DWORD dwShareMode,
  631. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  632. DWORD dwCreationDisposition,
  633. DWORD dwFlagsAndAttributes,
  634. HANDLE hTemplateFile,
  635. BOOL TranslatePath
  636. )
  637. {
  638. NTSTATUS Status;
  639. OBJECT_ATTRIBUTES Obja;
  640. HANDLE Handle;
  641. UNICODE_STRING FileName;
  642. IO_STATUS_BLOCK IoStatusBlock;
  643. BOOLEAN TranslationStatus;
  644. PVOID FreeBuffer;
  645. ULONG CreateDisposition;
  646. ULONG CreateFlags = 0;
  647. FILE_ALLOCATION_INFORMATION AllocationInfo;
  648. PUNICODE_STRING lpConsoleName;
  649. BOOL bInheritHandle;
  650. BOOL EndsInSlash;
  651. DWORD SQOSFlags;
  652. BOOLEAN ContextTrackingMode = FALSE;
  653. BOOLEAN EffectiveOnly = FALSE;
  654. SECURITY_IMPERSONATION_LEVEL ImpersonationLevel = SecurityAnonymous;
  655. SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
  656. if (ARGUMENT_PRESENT(hTemplateFile))
  657. {
  658. return INVALID_HANDLE_VALUE;
  659. }
  660. switch ( dwCreationDisposition )
  661. {
  662. case CREATE_NEW :
  663. CreateDisposition = FILE_CREATE;
  664. break;
  665. case CREATE_ALWAYS :
  666. CreateDisposition = FILE_OVERWRITE_IF;
  667. break;
  668. case OPEN_EXISTING :
  669. CreateDisposition = FILE_OPEN;
  670. break;
  671. case OPEN_ALWAYS :
  672. CreateDisposition = FILE_OPEN_IF;
  673. break;
  674. case TRUNCATE_EXISTING :
  675. CreateDisposition = FILE_OPEN;
  676. if ( !(dwDesiredAccess & GENERIC_WRITE) )
  677. {
  678. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  679. return INVALID_HANDLE_VALUE;
  680. }
  681. break;
  682. default :
  683. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  684. return INVALID_HANDLE_VALUE;
  685. }
  686. RtlInitUnicodeString(&FileName,lpFileName);
  687. if (TranslatePath)
  688. {
  689. TranslationStatus = RtlDosPathNameToNtPathName_U(lpFileName,
  690. &FileName,
  691. NULL,
  692. NULL
  693. );
  694. if ( !TranslationStatus )
  695. {
  696. SetLastError(ERROR_PATH_NOT_FOUND);
  697. return INVALID_HANDLE_VALUE;
  698. }
  699. FreeBuffer = FileName.Buffer;
  700. }
  701. else
  702. {
  703. FreeBuffer = NULL;
  704. }
  705. InitializeObjectAttributes(&Obja,
  706. &FileName,
  707. (dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS) ? 0 : OBJ_CASE_INSENSITIVE,
  708. NULL,
  709. NULL
  710. );
  711. SQOSFlags = dwFlagsAndAttributes & SECURITY_VALID_SQOS_FLAGS;
  712. if ( SQOSFlags & SECURITY_SQOS_PRESENT )
  713. {
  714. SQOSFlags &= ~SECURITY_SQOS_PRESENT;
  715. if (SQOSFlags & SECURITY_CONTEXT_TRACKING)
  716. {
  717. SecurityQualityOfService.ContextTrackingMode = (SECURITY_CONTEXT_TRACKING_MODE) TRUE;
  718. SQOSFlags &= ~SECURITY_CONTEXT_TRACKING;
  719. }
  720. else
  721. {
  722. SecurityQualityOfService.ContextTrackingMode = (SECURITY_CONTEXT_TRACKING_MODE) FALSE;
  723. }
  724. if (SQOSFlags & SECURITY_EFFECTIVE_ONLY)
  725. {
  726. SecurityQualityOfService.EffectiveOnly = TRUE;
  727. SQOSFlags &= ~SECURITY_EFFECTIVE_ONLY;
  728. }
  729. else
  730. {
  731. SecurityQualityOfService.EffectiveOnly = FALSE;
  732. }
  733. SecurityQualityOfService.ImpersonationLevel = (SECURITY_IMPERSONATION_LEVEL)(SQOSFlags >> 16);
  734. }
  735. else
  736. {
  737. SecurityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  738. SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation;
  739. SecurityQualityOfService.EffectiveOnly = TRUE;
  740. }
  741. SecurityQualityOfService.Length = sizeof( SECURITY_QUALITY_OF_SERVICE );
  742. Obja.SecurityQualityOfService = &SecurityQualityOfService;
  743. if ( ARGUMENT_PRESENT(lpSecurityAttributes) )
  744. {
  745. Obja.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
  746. if ( lpSecurityAttributes->bInheritHandle )
  747. {
  748. Obja.Attributes |= OBJ_INHERIT;
  749. }
  750. }
  751. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING ? FILE_NO_INTERMEDIATE_BUFFERING : 0 );
  752. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH ? FILE_WRITE_THROUGH : 0 );
  753. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED ? 0 : FILE_SYNCHRONOUS_IO_NONALERT );
  754. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN ? FILE_SEQUENTIAL_ONLY : 0 );
  755. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS ? FILE_RANDOM_ACCESS : 0 );
  756. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS ? FILE_OPEN_FOR_BACKUP_INTENT : 0 );
  757. if ( dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE )
  758. {
  759. CreateFlags |= FILE_DELETE_ON_CLOSE;
  760. dwDesiredAccess |= DELETE;
  761. }
  762. if ( dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT )
  763. {
  764. CreateFlags |= FILE_OPEN_REPARSE_POINT;
  765. }
  766. if ( dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL )
  767. {
  768. CreateFlags |= FILE_OPEN_NO_RECALL;
  769. }
  770. //
  771. // Backup semantics allow directories to be opened
  772. //
  773. if ( !(dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS) )
  774. {
  775. CreateFlags |= FILE_NON_DIRECTORY_FILE;
  776. }
  777. else
  778. {
  779. //
  780. // Backup intent was specified... Now look to see if we are to allow
  781. // directory creation
  782. //
  783. if ( (dwFlagsAndAttributes & FILE_ATTRIBUTE_DIRECTORY ) &&
  784. (dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS ) &&
  785. (CreateDisposition == FILE_CREATE) )
  786. {
  787. CreateFlags |= FILE_DIRECTORY_FILE;
  788. }
  789. }
  790. Status = NtCreateFile(&Handle,
  791. (ACCESS_MASK)dwDesiredAccess | SYNCHRONIZE | FILE_READ_ATTRIBUTES,
  792. &Obja,
  793. &IoStatusBlock,
  794. NULL,
  795. dwFlagsAndAttributes & (FILE_ATTRIBUTE_VALID_FLAGS & ~FILE_ATTRIBUTE_DIRECTORY),
  796. dwShareMode,
  797. CreateDisposition,
  798. CreateFlags,
  799. NULL,
  800. 0
  801. );
  802. if (FreeBuffer != NULL)
  803. {
  804. RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
  805. }
  806. if ( !NT_SUCCESS(Status) )
  807. {
  808. BaseSetLastNTError(Status);
  809. if ( Status == STATUS_OBJECT_NAME_COLLISION )
  810. {
  811. SetLastError(ERROR_FILE_EXISTS);
  812. }
  813. else if ( Status == STATUS_FILE_IS_A_DIRECTORY )
  814. {
  815. SetLastError(ERROR_ACCESS_DENIED);
  816. }
  817. return INVALID_HANDLE_VALUE;
  818. }
  819. //
  820. // if NT returns supersede/overwritten, it means that a create_always, openalways
  821. // found an existing copy of the file. In this case ERROR_ALREADY_EXISTS is returned
  822. //
  823. if ( (dwCreationDisposition == CREATE_ALWAYS && IoStatusBlock.Information ==
  824. FILE_OVERWRITTEN) ||
  825. (dwCreationDisposition == OPEN_ALWAYS && IoStatusBlock.Information == FILE_OPENED) )
  826. {
  827. SetLastError(ERROR_ALREADY_EXISTS);
  828. }
  829. else
  830. {
  831. SetLastError(0);
  832. }
  833. //
  834. // Truncate the file if required
  835. //
  836. if ( dwCreationDisposition == TRUNCATE_EXISTING)
  837. {
  838. AllocationInfo.AllocationSize.QuadPart = 0;
  839. Status = NtSetInformationFile(Handle,
  840. &IoStatusBlock,
  841. &AllocationInfo,
  842. sizeof(AllocationInfo),
  843. FileAllocationInformation
  844. );
  845. if ( !NT_SUCCESS(Status) )
  846. {
  847. BaseSetLastNTError(Status);
  848. NtClose(Handle);
  849. Handle = INVALID_HANDLE_VALUE;
  850. }
  851. }
  852. return Handle;
  853. }
  854. HANDLE
  855. WINAPI
  856. NtNativeCreateFileA(
  857. LPCSTR lpFileName,
  858. DWORD dwDesiredAccess,
  859. DWORD dwShareMode,
  860. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  861. DWORD dwCreationDisposition,
  862. DWORD dwFlagsAndAttributes,
  863. HANDLE hTemplateFile,
  864. BOOL TranslatePath
  865. )
  866. {
  867. NTSTATUS Status;
  868. ANSI_STRING AnsiFile;
  869. UNICODE_STRING WideFile;
  870. RtlInitAnsiString(&AnsiFile, lpFileName);
  871. Status = RtlAnsiStringToUnicodeString(&WideFile, &AnsiFile, TRUE);
  872. if (!NT_SUCCESS(Status))
  873. {
  874. BaseSetLastNTError(Status);
  875. return FALSE;
  876. }
  877. HANDLE File;
  878. File = NtNativeCreateFileW(WideFile.Buffer, dwDesiredAccess, dwShareMode,
  879. lpSecurityAttributes, dwCreationDisposition,
  880. dwFlagsAndAttributes, hTemplateFile,
  881. TranslatePath);
  882. RtlFreeUnicodeString(&WideFile);
  883. return File;
  884. }
  885. HANDLE
  886. WINAPI
  887. CreateFileA(
  888. LPCSTR lpFileName,
  889. DWORD dwDesiredAccess,
  890. DWORD dwShareMode,
  891. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  892. DWORD dwCreationDisposition,
  893. DWORD dwFlagsAndAttributes,
  894. HANDLE hTemplateFile
  895. )
  896. {
  897. return NtNativeCreateFileA(lpFileName, dwDesiredAccess, dwShareMode,
  898. lpSecurityAttributes, dwCreationDisposition,
  899. dwFlagsAndAttributes, hTemplateFile,
  900. TRUE);
  901. }
  902. BOOL
  903. WINAPI
  904. DeviceIoControl(
  905. HANDLE hDevice,
  906. DWORD dwIoControlCode,
  907. LPVOID lpInBuffer,
  908. DWORD nInBufferSize,
  909. LPVOID lpOutBuffer,
  910. DWORD nOutBufferSize,
  911. LPDWORD lpBytesReturned,
  912. LPOVERLAPPED lpOverlapped
  913. )
  914. {
  915. if ((dwIoControlCode >> 16) == FILE_DEVICE_FILE_SYSTEM ||
  916. lpOverlapped != NULL)
  917. {
  918. return FALSE;
  919. }
  920. IO_STATUS_BLOCK Iosb;
  921. NTSTATUS Status;
  922. Status = NtDeviceIoControlFile(hDevice,
  923. NULL,
  924. NULL, // APC routine
  925. NULL, // APC Context
  926. &Iosb,
  927. dwIoControlCode, // IoControlCode
  928. lpInBuffer, // Buffer for data to the FS
  929. nInBufferSize,
  930. lpOutBuffer, // OutputBuffer for data from the FS
  931. nOutBufferSize // OutputBuffer Length
  932. );
  933. if ( Status == STATUS_PENDING)
  934. {
  935. // Operation must complete before return & Iosb destroyed
  936. Status = NtWaitForSingleObject( hDevice, FALSE, NULL );
  937. if ( NT_SUCCESS(Status))
  938. {
  939. Status = Iosb.Status;
  940. }
  941. }
  942. if ( NT_SUCCESS(Status) )
  943. {
  944. *lpBytesReturned = (DWORD)Iosb.Information;
  945. return TRUE;
  946. }
  947. else
  948. {
  949. // handle warning value STATUS_BUFFER_OVERFLOW somewhat correctly
  950. if ( !NT_ERROR(Status) )
  951. {
  952. *lpBytesReturned = (DWORD)Iosb.Information;
  953. }
  954. BaseSetLastNTError(Status);
  955. return FALSE;
  956. }
  957. }
  958. BOOL
  959. WINAPI
  960. ReadFile(
  961. HANDLE hFile,
  962. LPVOID lpBuffer,
  963. DWORD nNumberOfBytesToRead,
  964. LPDWORD lpNumberOfBytesRead,
  965. LPOVERLAPPED lpOverlapped
  966. )
  967. {
  968. NTSTATUS Status;
  969. IO_STATUS_BLOCK IoStatusBlock;
  970. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) )
  971. {
  972. *lpNumberOfBytesRead = 0;
  973. }
  974. if ( ARGUMENT_PRESENT( lpOverlapped ) )
  975. {
  976. LARGE_INTEGER Li;
  977. lpOverlapped->Internal = (DWORD)STATUS_PENDING;
  978. Li.LowPart = lpOverlapped->Offset;
  979. Li.HighPart = lpOverlapped->OffsetHigh;
  980. Status = NtReadFile(
  981. hFile,
  982. lpOverlapped->hEvent,
  983. NULL,
  984. (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped,
  985. (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  986. lpBuffer,
  987. nNumberOfBytesToRead,
  988. &Li,
  989. NULL
  990. );
  991. if ( NT_SUCCESS(Status) && Status != STATUS_PENDING)
  992. {
  993. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) )
  994. {
  995. __try
  996. {
  997. *lpNumberOfBytesRead = (DWORD)lpOverlapped->InternalHigh;
  998. }
  999. __except(EXCEPTION_EXECUTE_HANDLER)
  1000. {
  1001. *lpNumberOfBytesRead = 0;
  1002. }
  1003. }
  1004. return TRUE;
  1005. }
  1006. else if (Status == STATUS_END_OF_FILE)
  1007. {
  1008. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) )
  1009. {
  1010. *lpNumberOfBytesRead = 0;
  1011. }
  1012. BaseSetLastNTError(Status);
  1013. return FALSE;
  1014. }
  1015. else
  1016. {
  1017. BaseSetLastNTError(Status);
  1018. return FALSE;
  1019. }
  1020. }
  1021. else
  1022. {
  1023. Status = NtReadFile(hFile,
  1024. NULL,
  1025. NULL,
  1026. NULL,
  1027. &IoStatusBlock,
  1028. lpBuffer,
  1029. nNumberOfBytesToRead,
  1030. NULL,
  1031. NULL
  1032. );
  1033. if ( Status == STATUS_PENDING)
  1034. {
  1035. // Operation must complete before return & IoStatusBlock destroyed
  1036. Status = NtWaitForSingleObject( hFile, FALSE, NULL );
  1037. if ( NT_SUCCESS(Status))
  1038. {
  1039. Status = IoStatusBlock.Status;
  1040. }
  1041. }
  1042. if ( NT_SUCCESS(Status) )
  1043. {
  1044. *lpNumberOfBytesRead = (DWORD)IoStatusBlock.Information;
  1045. return TRUE;
  1046. }
  1047. else
  1048. {
  1049. if (Status == STATUS_END_OF_FILE)
  1050. {
  1051. *lpNumberOfBytesRead = 0;
  1052. return TRUE;
  1053. }
  1054. else
  1055. {
  1056. if ( NT_WARNING(Status) )
  1057. {
  1058. *lpNumberOfBytesRead = (DWORD)IoStatusBlock.Information;
  1059. }
  1060. BaseSetLastNTError(Status);
  1061. return FALSE;
  1062. }
  1063. }
  1064. }
  1065. }
  1066. BOOL
  1067. WINAPI
  1068. WriteFile(
  1069. HANDLE hFile,
  1070. LPCVOID lpBuffer,
  1071. DWORD nNumberOfBytesToWrite,
  1072. LPDWORD lpNumberOfBytesWritten,
  1073. LPOVERLAPPED lpOverlapped
  1074. )
  1075. {
  1076. NTSTATUS Status;
  1077. IO_STATUS_BLOCK IoStatusBlock;
  1078. if ( ARGUMENT_PRESENT(lpNumberOfBytesWritten) )
  1079. {
  1080. *lpNumberOfBytesWritten = 0;
  1081. }
  1082. if ( ARGUMENT_PRESENT( lpOverlapped ) )
  1083. {
  1084. LARGE_INTEGER Li;
  1085. lpOverlapped->Internal = (DWORD)STATUS_PENDING;
  1086. Li.LowPart = lpOverlapped->Offset;
  1087. Li.HighPart = lpOverlapped->OffsetHigh;
  1088. Status = NtWriteFile(
  1089. hFile,
  1090. lpOverlapped->hEvent,
  1091. NULL,
  1092. (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped,
  1093. (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  1094. (PVOID)lpBuffer,
  1095. nNumberOfBytesToWrite,
  1096. &Li,
  1097. NULL
  1098. );
  1099. if ( !NT_ERROR(Status) && Status != STATUS_PENDING)
  1100. {
  1101. if ( ARGUMENT_PRESENT(lpNumberOfBytesWritten) )
  1102. {
  1103. __try
  1104. {
  1105. *lpNumberOfBytesWritten = (DWORD)lpOverlapped->InternalHigh;
  1106. }
  1107. __except(EXCEPTION_EXECUTE_HANDLER)
  1108. {
  1109. *lpNumberOfBytesWritten = 0;
  1110. }
  1111. }
  1112. return TRUE;
  1113. }
  1114. else
  1115. {
  1116. BaseSetLastNTError(Status);
  1117. return FALSE;
  1118. }
  1119. }
  1120. else
  1121. {
  1122. Status = NtWriteFile(hFile,
  1123. NULL,
  1124. NULL,
  1125. NULL,
  1126. &IoStatusBlock,
  1127. (PVOID)lpBuffer,
  1128. nNumberOfBytesToWrite,
  1129. NULL,
  1130. NULL
  1131. );
  1132. if ( Status == STATUS_PENDING)
  1133. {
  1134. // Operation must complete before return & IoStatusBlock destroyed
  1135. Status = NtWaitForSingleObject( hFile, FALSE, NULL );
  1136. if ( NT_SUCCESS(Status))
  1137. {
  1138. Status = IoStatusBlock.Status;
  1139. }
  1140. }
  1141. if ( NT_SUCCESS(Status))
  1142. {
  1143. *lpNumberOfBytesWritten = (DWORD)IoStatusBlock.Information;
  1144. return TRUE;
  1145. }
  1146. else
  1147. {
  1148. if ( NT_WARNING(Status) )
  1149. {
  1150. *lpNumberOfBytesWritten = (DWORD)IoStatusBlock.Information;
  1151. }
  1152. BaseSetLastNTError(Status);
  1153. return FALSE;
  1154. }
  1155. }
  1156. }
  1157. SIZE_T
  1158. WINAPI
  1159. VirtualQueryEx(
  1160. HANDLE hProcess,
  1161. LPCVOID lpAddress,
  1162. PMEMORY_BASIC_INFORMATION lpBuffer,
  1163. SIZE_T dwLength
  1164. )
  1165. {
  1166. NTSTATUS Status;
  1167. SIZE_T ReturnLength = 0;
  1168. Status = NtQueryVirtualMemory( hProcess,
  1169. (LPVOID)lpAddress,
  1170. MemoryBasicInformation,
  1171. (PMEMORY_BASIC_INFORMATION)lpBuffer,
  1172. dwLength,
  1173. &ReturnLength
  1174. );
  1175. if (NT_SUCCESS( Status ))
  1176. {
  1177. return( ReturnLength );
  1178. }
  1179. else
  1180. {
  1181. BaseSetLastNTError( Status );
  1182. return( 0 );
  1183. }
  1184. }
  1185. BOOL
  1186. WINAPI
  1187. VirtualProtectEx(
  1188. HANDLE hProcess,
  1189. PVOID lpAddress,
  1190. SIZE_T dwSize,
  1191. DWORD flNewProtect,
  1192. PDWORD lpflOldProtect
  1193. )
  1194. {
  1195. NTSTATUS Status;
  1196. Status = NtProtectVirtualMemory( hProcess,
  1197. &lpAddress,
  1198. &dwSize,
  1199. flNewProtect,
  1200. lpflOldProtect
  1201. );
  1202. if (NT_SUCCESS( Status )) {
  1203. return( TRUE );
  1204. }
  1205. else {
  1206. if (Status == STATUS_INVALID_PAGE_PROTECTION) {
  1207. if (hProcess == NtCurrentProcess()) {
  1208. //
  1209. // Unlock any pages that were locked with MmSecureVirtualMemory.
  1210. // This is useful for SANs.
  1211. //
  1212. if (RtlFlushSecureMemoryCache(lpAddress, dwSize)) {
  1213. Status = NtProtectVirtualMemory( hProcess,
  1214. &lpAddress,
  1215. &dwSize,
  1216. flNewProtect,
  1217. lpflOldProtect
  1218. );
  1219. if (NT_SUCCESS( Status )) {
  1220. return( TRUE );
  1221. }
  1222. }
  1223. }
  1224. }
  1225. BaseSetLastNTError( Status );
  1226. return( FALSE );
  1227. }
  1228. }
  1229. PVOID
  1230. WINAPI
  1231. VirtualAllocEx(
  1232. HANDLE hProcess,
  1233. PVOID lpAddress,
  1234. SIZE_T dwSize,
  1235. DWORD flAllocationType,
  1236. DWORD flProtect
  1237. )
  1238. {
  1239. NTSTATUS Status;
  1240. __try {
  1241. Status = NtAllocateVirtualMemory( hProcess,
  1242. &lpAddress,
  1243. 0,
  1244. &dwSize,
  1245. flAllocationType,
  1246. flProtect
  1247. );
  1248. }
  1249. __except( EXCEPTION_EXECUTE_HANDLER ) {
  1250. Status = GetExceptionCode();
  1251. }
  1252. if (NT_SUCCESS( Status )) {
  1253. return( lpAddress );
  1254. }
  1255. else {
  1256. BaseSetLastNTError( Status );
  1257. return( NULL );
  1258. }
  1259. }
  1260. BOOL
  1261. WINAPI
  1262. VirtualFreeEx(
  1263. HANDLE hProcess,
  1264. LPVOID lpAddress,
  1265. SIZE_T dwSize,
  1266. DWORD dwFreeType
  1267. )
  1268. {
  1269. NTSTATUS Status;
  1270. if ( (dwFreeType & MEM_RELEASE ) && dwSize != 0 ) {
  1271. BaseSetLastNTError( STATUS_INVALID_PARAMETER );
  1272. return FALSE;
  1273. }
  1274. Status = NtFreeVirtualMemory( hProcess,
  1275. &lpAddress,
  1276. &dwSize,
  1277. dwFreeType
  1278. );
  1279. if (NT_SUCCESS( Status )) {
  1280. return( TRUE );
  1281. }
  1282. else {
  1283. if (Status == STATUS_INVALID_PAGE_PROTECTION) {
  1284. if (hProcess == NtCurrentProcess()) {
  1285. //
  1286. // Unlock any pages that were locked with MmSecureVirtualMemory.
  1287. // This is useful for SANs.
  1288. //
  1289. if (RtlFlushSecureMemoryCache(lpAddress, dwSize)) {
  1290. Status = NtFreeVirtualMemory( hProcess,
  1291. &lpAddress,
  1292. &dwSize,
  1293. dwFreeType
  1294. );
  1295. if (NT_SUCCESS( Status )) {
  1296. return( TRUE );
  1297. }
  1298. }
  1299. }
  1300. }
  1301. BaseSetLastNTError( Status );
  1302. return( FALSE );
  1303. }
  1304. }
  1305. HANDLE
  1306. APIENTRY
  1307. CreateThread(
  1308. LPSECURITY_ATTRIBUTES lpThreadAttributes,
  1309. SIZE_T dwStackSize,
  1310. LPTHREAD_START_ROUTINE lpStartAddress,
  1311. LPVOID lpParameter,
  1312. DWORD dwCreationFlags,
  1313. LPDWORD lpThreadId
  1314. )
  1315. {
  1316. return CreateRemoteThread( NtCurrentProcess(),
  1317. lpThreadAttributes,
  1318. dwStackSize,
  1319. lpStartAddress,
  1320. lpParameter,
  1321. dwCreationFlags,
  1322. lpThreadId
  1323. );
  1324. }
  1325. HANDLE
  1326. APIENTRY
  1327. CreateRemoteThread(
  1328. HANDLE hProcess,
  1329. LPSECURITY_ATTRIBUTES lpThreadAttributes,
  1330. SIZE_T dwStackSize,
  1331. LPTHREAD_START_ROUTINE lpStartAddress,
  1332. LPVOID lpParameter,
  1333. DWORD dwCreationFlags,
  1334. LPDWORD lpThreadId
  1335. )
  1336. {
  1337. NTSTATUS Status;
  1338. HANDLE Handle;
  1339. CLIENT_ID ClientId;
  1340. Handle = NULL;
  1341. //
  1342. // Allocate a stack for this thread in the address space of the target
  1343. // process.
  1344. //
  1345. if ((dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION) ||
  1346. dwStackSize != 0 || lpThreadAttributes != NULL)
  1347. {
  1348. return NULL;
  1349. }
  1350. Status = RtlCreateUserThread (hProcess,
  1351. NULL,
  1352. (dwCreationFlags & CREATE_SUSPENDED) ?
  1353. TRUE : FALSE,
  1354. 0,
  1355. 0,
  1356. 0,
  1357. (PUSER_THREAD_START_ROUTINE)lpStartAddress,
  1358. lpParameter,
  1359. &Handle,
  1360. &ClientId);
  1361. if ( ARGUMENT_PRESENT(lpThreadId) )
  1362. {
  1363. *lpThreadId = HandleToUlong(ClientId.UniqueThread);
  1364. }
  1365. return Handle;
  1366. }
  1367. #define DOS_LOCAL_PIPE_PREFIX L"\\\\.\\pipe\\"
  1368. #define DOS_LOCAL_PIPE L"\\DosDevices\\pipe\\"
  1369. #define DOS_REMOTE_PIPE L"\\DosDevices\\UNC\\"
  1370. #define INVALID_PIPE_MODE_BITS ~(PIPE_READMODE_BYTE \
  1371. | PIPE_READMODE_MESSAGE \
  1372. | PIPE_WAIT \
  1373. | PIPE_NOWAIT)
  1374. HANDLE
  1375. APIENTRY
  1376. NtNativeCreateNamedPipeW(
  1377. LPCWSTR lpName,
  1378. DWORD dwOpenMode,
  1379. DWORD dwPipeMode,
  1380. DWORD nMaxInstances,
  1381. DWORD nOutBufferSize,
  1382. DWORD nInBufferSize,
  1383. DWORD nDefaultTimeOut,
  1384. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  1385. BOOL TranslatePath
  1386. )
  1387. /*++
  1388. Parameters:
  1389. lpName --Supplies the pipe name Documented in "Pipe Names" section
  1390. earlier. This must be a local name.
  1391. dwOpenMode --Supplies the set of flags that define the mode which the
  1392. pipe is to be opened with. The open mode consists of access
  1393. flags (one of three values) logically ORed with a writethrough
  1394. flag (one of two values) and an overlapped flag (one of two
  1395. values), as described below.
  1396. dwOpenMode Flags:
  1397. PIPE_ACCESS_DUPLEX --Pipe is bidirectional. (This is
  1398. semantically equivalent to calling CreateFile with access
  1399. flags of GENERIC_READ | GENERIC_WRITE.)
  1400. PIPE_ACCESS_INBOUND --Data goes from client to server only.
  1401. (This is semantically equivalent to calling CreateFile with
  1402. access flags of GENERIC_READ.)
  1403. PIPE_ACCESS_OUTBOUND --Data goes from server to client only.
  1404. (This is semantically equivalent to calling CreateFile with
  1405. access flags of GENERIC_WRITE.)
  1406. PIPE_WRITETHROUGH --The redirector is not permitted to delay the
  1407. transmission of data to the named pipe buffer on the remote
  1408. server. This disables a performance enhancement for
  1409. applications that need synchronization with every write
  1410. operation.
  1411. FILE_FLAG_OVERLAPPED --Indicates that the system should
  1412. initialize the file so that ReadFile, WriteFile and other
  1413. operations that may take a significant time to process will
  1414. return ERROR_IO_PENDING. An event will be set to the
  1415. signalled state when the operation completes.
  1416. FILE_FLAG_WRITETHROUGH -- No intermediate buffering.
  1417. WRITE_DAC -- Standard security desired access
  1418. WRITE_OWNER -- ditto
  1419. ACCESS_SYSTEM_SECURITY -- ditto
  1420. dwPipeMode --Supplies the pipe-specific modes (as flags) of the pipe.
  1421. This parameter is a combination of a read-mode flag, a type flag,
  1422. and a wait flag.
  1423. dwPipeMode Flags:
  1424. PIPE_WAIT --Blocking mode is to be used for this handle.
  1425. PIPE_NOWAIT --Nonblocking mode is to be used for this handle.
  1426. PIPE_READMODE_BYTE --Read pipe as a byte stream.
  1427. PIPE_READMODE_MESSAGE --Read pipe as a message stream. Note that
  1428. this is not allowed with PIPE_TYPE_BYTE.
  1429. PIPE_TYPE_BYTE --Pipe is a byte-stream pipe. Note that this is
  1430. not allowed with PIPE_READMODE_MESSAGE.
  1431. PIPE_TYPE_MESSAGE --Pipe is a message-stream pipe.
  1432. nMaxInstances --Gives the maximum number of instances for this pipe.
  1433. Acceptable values are 1 to PIPE_UNLIMITED_INSTANCES-1 and
  1434. PIPE_UNLIMITED_INSTANCES.
  1435. nMaxInstances Special Values:
  1436. PIPE_UNLIMITED_INSTANCES --Unlimited instances of this pipe can
  1437. be created.
  1438. nOutBufferSize --Specifies an advisory on the number of bytes to
  1439. reserve for the outgoing buffer.
  1440. nInBufferSize --Specifies an advisory on the number of bytes to
  1441. reserve for the incoming buffer.
  1442. nDefaultTimeOut -- Specifies an optional pointer to a timeout value
  1443. that is to be used if a timeout value is not specified when
  1444. waiting for an instance of a named pipe. This parameter is only
  1445. meaningful when the first instance of a named pipe is created. If
  1446. neither CreateNamedPipe or WaitNamedPipe specify a timeout 50
  1447. milliseconds will be used.
  1448. lpSecurityAttributes --An optional parameter that, if present and
  1449. supported on the target system, supplies a security descriptor
  1450. for the named pipe. This parameter includes an inheritance flag
  1451. for the handle. If this parameter is not present, the handle is
  1452. not inherited by child processes.
  1453. Return Value:
  1454. Returns one of the following:
  1455. INVALID_HANDLE_VALUE --An error occurred. Call GetLastError for more
  1456. information.
  1457. Anything else --Returns a handle for use in the server side of
  1458. subsequent named pipe operations.
  1459. --*/
  1460. {
  1461. NTSTATUS Status;
  1462. OBJECT_ATTRIBUTES Obja;
  1463. HANDLE Handle;
  1464. UNICODE_STRING FileName;
  1465. IO_STATUS_BLOCK IoStatusBlock;
  1466. BOOLEAN TranslationStatus;
  1467. LARGE_INTEGER Timeout;
  1468. PVOID FreeBuffer;
  1469. ULONG CreateFlags;
  1470. ULONG DesiredAccess;
  1471. ULONG ShareAccess;
  1472. ULONG MaxInstances;
  1473. SECURITY_DESCRIPTOR SecurityDescriptor;
  1474. PACL DefaultAcl = NULL;
  1475. if ((nMaxInstances == 0) ||
  1476. (nMaxInstances > PIPE_UNLIMITED_INSTANCES)) {
  1477. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  1478. return INVALID_HANDLE_VALUE;
  1479. }
  1480. // Convert Win32 maximum Instances to Nt maximum instances.
  1481. MaxInstances = (nMaxInstances == PIPE_UNLIMITED_INSTANCES)?
  1482. 0xffffffff : nMaxInstances;
  1483. if (TranslatePath)
  1484. {
  1485. TranslationStatus = RtlDosPathNameToNtPathName_U(
  1486. lpName,
  1487. &FileName,
  1488. NULL,
  1489. NULL
  1490. );
  1491. if ( !TranslationStatus ) {
  1492. SetLastError(ERROR_PATH_NOT_FOUND);
  1493. return INVALID_HANDLE_VALUE;
  1494. }
  1495. FreeBuffer = FileName.Buffer;
  1496. }
  1497. else
  1498. {
  1499. RtlInitUnicodeString(&FileName, lpName);
  1500. FreeBuffer = NULL;
  1501. }
  1502. InitializeObjectAttributes(
  1503. &Obja,
  1504. &FileName,
  1505. OBJ_CASE_INSENSITIVE,
  1506. NULL,
  1507. NULL
  1508. );
  1509. if ( ARGUMENT_PRESENT(lpSecurityAttributes) ) {
  1510. Obja.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
  1511. if ( lpSecurityAttributes->bInheritHandle ) {
  1512. Obja.Attributes |= OBJ_INHERIT;
  1513. }
  1514. }
  1515. if (Obja.SecurityDescriptor == NULL) {
  1516. //
  1517. // Apply default security if none specified (bug 131090)
  1518. //
  1519. Status = RtlDefaultNpAcl( &DefaultAcl );
  1520. if (NT_SUCCESS( Status )) {
  1521. RtlCreateSecurityDescriptor( &SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
  1522. RtlSetDaclSecurityDescriptor( &SecurityDescriptor, TRUE, DefaultAcl, FALSE );
  1523. Obja.SecurityDescriptor = &SecurityDescriptor;
  1524. } else {
  1525. if (FreeBuffer != NULL)
  1526. {
  1527. RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
  1528. }
  1529. BaseSetLastNTError(Status);
  1530. return INVALID_HANDLE_VALUE;
  1531. }
  1532. }
  1533. // End of code common with fileopcr.c CreateFile()
  1534. CreateFlags = (dwOpenMode & FILE_FLAG_WRITE_THROUGH ? FILE_WRITE_THROUGH : 0 );
  1535. CreateFlags |= (dwOpenMode & FILE_FLAG_OVERLAPPED ? 0 : FILE_SYNCHRONOUS_IO_NONALERT);
  1536. //
  1537. // Determine the timeout. Convert from milliseconds to an Nt delta time
  1538. //
  1539. if ( nDefaultTimeOut ) {
  1540. Timeout.QuadPart = - (LONGLONG)UInt32x32To64( 10 * 1000, nDefaultTimeOut );
  1541. }
  1542. else {
  1543. // Default timeout is 50 Milliseconds
  1544. Timeout.QuadPart = -10 * 1000 * 50;
  1545. }
  1546. // Check no reserved bits are set by mistake.
  1547. if (( dwOpenMode & ~(PIPE_ACCESS_DUPLEX |
  1548. FILE_FLAG_OVERLAPPED | FILE_FLAG_WRITE_THROUGH |
  1549. FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC |
  1550. WRITE_OWNER | ACCESS_SYSTEM_SECURITY ))||
  1551. ( dwPipeMode & ~(PIPE_NOWAIT | PIPE_READMODE_MESSAGE |
  1552. PIPE_TYPE_MESSAGE ))) {
  1553. if (FreeBuffer != NULL)
  1554. {
  1555. RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
  1556. }
  1557. if (DefaultAcl != NULL) {
  1558. RtlFreeHeap(RtlProcessHeap(),0,DefaultAcl);
  1559. }
  1560. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  1561. return INVALID_HANDLE_VALUE;
  1562. }
  1563. //
  1564. // Translate the open mode into a sharemode to restrict the clients access
  1565. // and derive the appropriate local desired access.
  1566. //
  1567. switch ( dwOpenMode & PIPE_ACCESS_DUPLEX ) {
  1568. case PIPE_ACCESS_INBOUND:
  1569. ShareAccess = FILE_SHARE_WRITE;
  1570. DesiredAccess = GENERIC_READ;
  1571. break;
  1572. case PIPE_ACCESS_OUTBOUND:
  1573. ShareAccess = FILE_SHARE_READ;
  1574. DesiredAccess = GENERIC_WRITE;
  1575. break;
  1576. case PIPE_ACCESS_DUPLEX:
  1577. ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
  1578. DesiredAccess = GENERIC_READ | GENERIC_WRITE;
  1579. break;
  1580. default:
  1581. if (FreeBuffer != NULL)
  1582. {
  1583. RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
  1584. }
  1585. if (DefaultAcl != NULL) {
  1586. RtlFreeHeap(RtlProcessHeap(),0,DefaultAcl);
  1587. }
  1588. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  1589. return INVALID_HANDLE_VALUE;
  1590. }
  1591. DesiredAccess |= SYNCHRONIZE |
  1592. ( dwOpenMode & (WRITE_DAC | WRITE_OWNER | ACCESS_SYSTEM_SECURITY ));
  1593. Status = NtCreateNamedPipeFile (
  1594. &Handle,
  1595. DesiredAccess,
  1596. &Obja,
  1597. &IoStatusBlock,
  1598. ShareAccess,
  1599. (dwOpenMode & FILE_FLAG_FIRST_PIPE_INSTANCE) ?
  1600. FILE_CREATE : FILE_OPEN_IF, // Create first instance or subsequent
  1601. CreateFlags, // Create Options
  1602. dwPipeMode & PIPE_TYPE_MESSAGE ?
  1603. FILE_PIPE_MESSAGE_TYPE : FILE_PIPE_BYTE_STREAM_TYPE,
  1604. dwPipeMode & PIPE_READMODE_MESSAGE ?
  1605. FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE,
  1606. dwPipeMode & PIPE_NOWAIT ?
  1607. FILE_PIPE_COMPLETE_OPERATION : FILE_PIPE_QUEUE_OPERATION,
  1608. MaxInstances, // Max instances
  1609. nInBufferSize, // Inbound quota
  1610. nOutBufferSize, // Outbound quota
  1611. (PLARGE_INTEGER)&Timeout
  1612. );
  1613. if ( Status == STATUS_NOT_SUPPORTED ||
  1614. Status == STATUS_INVALID_DEVICE_REQUEST ) {
  1615. //
  1616. // The request must have been processed by some other device driver
  1617. // (other than NPFS). Map the error to something reasonable.
  1618. //
  1619. Status = STATUS_OBJECT_NAME_INVALID;
  1620. }
  1621. if (FreeBuffer != NULL)
  1622. {
  1623. RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
  1624. }
  1625. if (DefaultAcl != NULL) {
  1626. RtlFreeHeap(RtlProcessHeap(),0,DefaultAcl);
  1627. }
  1628. if ( !NT_SUCCESS(Status) ) {
  1629. BaseSetLastNTError(Status);
  1630. return INVALID_HANDLE_VALUE;
  1631. }
  1632. return Handle;
  1633. }
  1634. HANDLE
  1635. APIENTRY
  1636. NtNativeCreateNamedPipeA(
  1637. LPCSTR lpName,
  1638. DWORD dwOpenMode,
  1639. DWORD dwPipeMode,
  1640. DWORD nMaxInstances,
  1641. DWORD nOutBufferSize,
  1642. DWORD nInBufferSize,
  1643. DWORD nDefaultTimeOut,
  1644. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  1645. BOOL TranslatePath
  1646. )
  1647. /*++
  1648. Ansi thunk to CreateNamedPipeW.
  1649. --*/
  1650. {
  1651. NTSTATUS Status;
  1652. PUNICODE_STRING Unicode;
  1653. ANSI_STRING AnsiString;
  1654. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  1655. RtlInitAnsiString(&AnsiString,lpName);
  1656. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  1657. if ( !NT_SUCCESS(Status) ) {
  1658. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  1659. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  1660. }
  1661. else {
  1662. BaseSetLastNTError(Status);
  1663. }
  1664. return INVALID_HANDLE_VALUE;
  1665. }
  1666. return NtNativeCreateNamedPipeW(
  1667. (LPCWSTR)Unicode->Buffer,
  1668. dwOpenMode,
  1669. dwPipeMode,
  1670. nMaxInstances,
  1671. nOutBufferSize,
  1672. nInBufferSize,
  1673. nDefaultTimeOut,
  1674. lpSecurityAttributes,
  1675. TranslatePath);
  1676. }
  1677. BOOL
  1678. APIENTRY
  1679. ConnectNamedPipe(
  1680. HANDLE hNamedPipe,
  1681. LPOVERLAPPED lpOverlapped
  1682. )
  1683. /*++
  1684. Routine Description:
  1685. The ConnectNamedPipe function is used by the server side of a named pipe
  1686. to wait for a client to connect to the named pipe with a CreateFile
  1687. request. The handle provided with the call to ConnectNamedPipe must have
  1688. been previously returned by a successful call to CreateNamedPipe. The pipe
  1689. must be in the disconnected, listening or connected states for
  1690. ConnectNamedPipe to succeed.
  1691. The behavior of this call depends on the blocking/nonblocking mode selected
  1692. with the PIPE_WAIT/PIPE_NOWAIT flags when the server end of the pipe was
  1693. created with CreateNamedPipe.
  1694. If blocking mode is specified, ConnectNamedPipe will change the state from
  1695. disconnected to listening and block. When a client connects with a
  1696. CreateFile, the state will be changed from listening to connected and the
  1697. ConnectNamedPipe returns TRUE. When the file handle is created with
  1698. FILE_FLAG_OVERLAPPED on a blocking mode pipe, the lpOverlapped parameter
  1699. can be specified. This allows the caller to continue processing while the
  1700. ConnectNamedPipe API awaits a connection. When the pipe enters the
  1701. signalled state the event is set to the signalled state.
  1702. When nonblocking is specified ConnectNamedPipe will not block. On the
  1703. first call the state will change from disconnected to listening. When a
  1704. client connects with an Open the state will be changed from listening to
  1705. connected. The ConnectNamedPipe will return FALSE (with GetLastError
  1706. returning ERROR_PIPE_LISTENING) until the state is changed to the listening
  1707. state.
  1708. Arguments:
  1709. hNamedPipe - Supplies a Handle to the server side of a named pipe.
  1710. lpOverlapped - Supplies an overlap structure to be used with the request.
  1711. If NULL then the API will not return until the operation completes. When
  1712. FILE_FLAG_OVERLAPPED is specified when the handle was created,
  1713. ConnectNamedPipe may return ERROR_IO_PENDING to allow the caller to
  1714. continue processing while the operation completes. The event (or File
  1715. handle if hEvent=NULL) will be set to the not signalled state before
  1716. ERROR_IO_PENDING is returned. The event will be set to the signalled
  1717. state upon completion of the request. GetOverlappedResult is used to
  1718. determine the error status.
  1719. Return Value:
  1720. TRUE -- The operation was successful, the pipe is in the
  1721. connected state.
  1722. FALSE -- The operation failed. Extended error status is available using
  1723. GetLastError.
  1724. --*/
  1725. {
  1726. NTSTATUS Status;
  1727. IO_STATUS_BLOCK Iosb;
  1728. if ( lpOverlapped ) {
  1729. lpOverlapped->Internal = (DWORD)STATUS_PENDING;
  1730. }
  1731. Status = NtFsControlFile(
  1732. hNamedPipe,
  1733. (lpOverlapped==NULL)? NULL : lpOverlapped->hEvent,
  1734. NULL, // ApcRoutine
  1735. lpOverlapped ? ((ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped) : NULL,
  1736. (lpOverlapped==NULL) ? &Iosb : (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  1737. FSCTL_PIPE_LISTEN,
  1738. NULL, // InputBuffer
  1739. 0, // InputBufferLength,
  1740. NULL, // OutputBuffer
  1741. 0 // OutputBufferLength
  1742. );
  1743. if ( lpOverlapped == NULL && Status == STATUS_PENDING) {
  1744. // Operation must complete before return & Iosb destroyed
  1745. Status = NtWaitForSingleObject( hNamedPipe, FALSE, NULL );
  1746. if ( NT_SUCCESS(Status)) {
  1747. Status = Iosb.Status;
  1748. }
  1749. }
  1750. if (NT_SUCCESS( Status ) && Status != STATUS_PENDING ) {
  1751. return TRUE;
  1752. }
  1753. else
  1754. {
  1755. BaseSetLastNTError(Status);
  1756. return FALSE;
  1757. }
  1758. }
  1759. BOOL
  1760. APIENTRY
  1761. WaitNamedPipeA(
  1762. LPCSTR lpNamedPipeName,
  1763. DWORD nTimeOut
  1764. )
  1765. /*++
  1766. Ansi thunk to WaitNamedPipeW
  1767. --*/
  1768. {
  1769. ANSI_STRING Ansi;
  1770. UNICODE_STRING UnicodeString;
  1771. BOOL b;
  1772. RtlInitAnsiString(&Ansi, lpNamedPipeName);
  1773. if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeString, &Ansi, TRUE))) {
  1774. return FALSE;
  1775. }
  1776. b = WaitNamedPipeW( UnicodeString.Buffer, nTimeOut );
  1777. RtlFreeUnicodeString(&UnicodeString);
  1778. return b;
  1779. }
  1780. BOOL
  1781. APIENTRY
  1782. WaitNamedPipeW(
  1783. LPCWSTR lpNamedPipeName,
  1784. DWORD nTimeOut
  1785. )
  1786. /*++
  1787. Routine Description:
  1788. The WaitNamedPipe function waits for a named pipe to become available.
  1789. Arguments:
  1790. lpNamedPipeName - Supplies the name of the named pipe.
  1791. nTimeOut - Gives a value (in milliseconds) that is the amount of time
  1792. this function should wait for the pipe to become available. (Note
  1793. that the function may take longer than that to execute, due to
  1794. various factors.)
  1795. nTimeOut Special Values:
  1796. NMPWAIT_WAIT_FOREVER
  1797. No timeout.
  1798. NMPWAIT_USE_DEFAULT_WAIT
  1799. Use default timeout set in call to CreateNamedPipe.
  1800. Return Value:
  1801. TRUE -- The operation was successful.
  1802. FALSE -- The operation failed. Extended error status is available using
  1803. GetLastError.
  1804. --*/
  1805. {
  1806. IO_STATUS_BLOCK Iosb;
  1807. OBJECT_ATTRIBUTES Obja;
  1808. NTSTATUS Status;
  1809. RTL_PATH_TYPE PathType;
  1810. ULONG WaitPipeLength;
  1811. PFILE_PIPE_WAIT_FOR_BUFFER WaitPipe;
  1812. PWSTR FreeBuffer;
  1813. UNICODE_STRING FileSystem;
  1814. UNICODE_STRING PipeName;
  1815. UNICODE_STRING OriginalPipeName;
  1816. UNICODE_STRING ValidUnicodePrefix;
  1817. HANDLE Handle;
  1818. IO_STATUS_BLOCK IoStatusBlock;
  1819. LPWSTR Pwc;
  1820. ULONG Index;
  1821. //
  1822. // Open a handle either to the redirector or the NPFS depending on
  1823. // the start of the pipe name. Split lpNamedPipeName into two
  1824. // halves as follows:
  1825. // \\.\pipe\pipename \\.\pipe\ and pipename
  1826. // \\server\pipe\pipename \\ and server\pipe\pipename
  1827. //
  1828. if (!RtlCreateUnicodeString( &OriginalPipeName, lpNamedPipeName)) {
  1829. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1830. return FALSE;
  1831. }
  1832. //
  1833. // Change all the forward slashes into backward slashes.
  1834. //
  1835. for ( Index =0; Index < (OriginalPipeName.Length/sizeof(WCHAR)); Index++ ) {
  1836. if (OriginalPipeName.Buffer[Index] == L'/') {
  1837. OriginalPipeName.Buffer[Index] = L'\\';
  1838. }
  1839. }
  1840. PipeName = OriginalPipeName;
  1841. PathType = RtlDetermineDosPathNameType_U(lpNamedPipeName);
  1842. FreeBuffer = NULL;
  1843. switch ( PathType ) {
  1844. case RtlPathTypeLocalDevice:
  1845. // Name should be of the form \\.\pipe\pipename (IgnoreCase)
  1846. RtlInitUnicodeString( &ValidUnicodePrefix, DOS_LOCAL_PIPE_PREFIX);
  1847. if (RtlPrefixString((PSTRING)&ValidUnicodePrefix,
  1848. (PSTRING)&PipeName,
  1849. TRUE) == FALSE) {
  1850. RtlFreeUnicodeString(&OriginalPipeName);
  1851. BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
  1852. return FALSE;
  1853. }
  1854. // Skip first 9 characters "\\.\pipe\"
  1855. PipeName.Buffer+=9;
  1856. PipeName.Length-=9*sizeof(WCHAR);
  1857. RtlInitUnicodeString( &FileSystem, DOS_LOCAL_PIPE);
  1858. break;
  1859. case RtlPathTypeUncAbsolute:
  1860. // Name is of the form \\server\pipe\pipename
  1861. // Find the pipe name.
  1862. for ( Pwc = &PipeName.Buffer[2]; *Pwc != 0; Pwc++) {
  1863. if ( *Pwc == L'\\') {
  1864. // Found backslash after servername
  1865. break;
  1866. }
  1867. }
  1868. if ( (*Pwc != 0) &&
  1869. ( _wcsnicmp( Pwc + 1, L"pipe\\", 5 ) == 0 ) ) {
  1870. // Temporarily, break this up into 2 strings
  1871. // string1 = \\server\pipe
  1872. // string2 = the-rest
  1873. Pwc += (sizeof (L"pipe\\") / sizeof( WCHAR ) ) - 1;
  1874. } else {
  1875. // This is not a valid remote path name.
  1876. RtlFreeUnicodeString(&OriginalPipeName);
  1877. BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
  1878. return FALSE;
  1879. }
  1880. // Pwc now points to the first path seperator after \\server\pipe.
  1881. // Attempt to open \DosDevices\Unc\Servername\Pipe.
  1882. PipeName.Buffer = &PipeName.Buffer[2];
  1883. PipeName.Length = (USHORT)((PCHAR)Pwc - (PCHAR)PipeName.Buffer);
  1884. PipeName.MaximumLength = PipeName.Length;
  1885. FileSystem.MaximumLength =
  1886. (USHORT)sizeof( DOS_REMOTE_PIPE ) +
  1887. PipeName.MaximumLength;
  1888. FileSystem.Buffer = (PWSTR)RtlAllocateHeap(
  1889. RtlProcessHeap(), 0,
  1890. FileSystem.MaximumLength
  1891. );
  1892. if ( !FileSystem.Buffer ) {
  1893. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1894. RtlFreeUnicodeString(&OriginalPipeName);
  1895. return FALSE;
  1896. }
  1897. FreeBuffer = FileSystem.Buffer;
  1898. RtlCopyMemory(
  1899. FileSystem.Buffer,
  1900. DOS_REMOTE_PIPE,
  1901. sizeof( DOS_REMOTE_PIPE ) - sizeof(WCHAR)
  1902. );
  1903. FileSystem.Length = sizeof( DOS_REMOTE_PIPE ) - sizeof(WCHAR);
  1904. RtlAppendUnicodeStringToString( &FileSystem, &PipeName );
  1905. // Set up pipe name, skip leading backslashes.
  1906. RtlInitUnicodeString( &PipeName, (PWCH)Pwc + 1 );
  1907. break;
  1908. default:
  1909. BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
  1910. RtlFreeUnicodeString(&OriginalPipeName);
  1911. return FALSE;
  1912. }
  1913. InitializeObjectAttributes(
  1914. &Obja,
  1915. &FileSystem,
  1916. OBJ_CASE_INSENSITIVE,
  1917. NULL,
  1918. NULL
  1919. );
  1920. Status = NtOpenFile(
  1921. &Handle,
  1922. (ACCESS_MASK)FILE_READ_ATTRIBUTES | SYNCHRONIZE,
  1923. &Obja,
  1924. &IoStatusBlock,
  1925. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1926. FILE_SYNCHRONOUS_IO_NONALERT
  1927. );
  1928. if (FreeBuffer != NULL) {
  1929. RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
  1930. }
  1931. if ( !NT_SUCCESS(Status) ) {
  1932. RtlFreeUnicodeString(&OriginalPipeName);
  1933. BaseSetLastNTError(Status);
  1934. return FALSE;
  1935. }
  1936. WaitPipeLength =
  1937. FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name[0]) + PipeName.Length;
  1938. WaitPipe = (PFILE_PIPE_WAIT_FOR_BUFFER)
  1939. RtlAllocateHeap(RtlProcessHeap(), 0, WaitPipeLength);
  1940. if ( !WaitPipe ) {
  1941. RtlFreeUnicodeString(&OriginalPipeName);
  1942. NtClose(Handle);
  1943. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1944. return FALSE;
  1945. }
  1946. if ( nTimeOut == NMPWAIT_USE_DEFAULT_WAIT ) {
  1947. WaitPipe->TimeoutSpecified = FALSE;
  1948. }
  1949. else {
  1950. if ( nTimeOut == NMPWAIT_WAIT_FOREVER ) {
  1951. WaitPipe->Timeout.LowPart = 0;
  1952. WaitPipe->Timeout.HighPart =0x80000000;
  1953. }
  1954. else {
  1955. //
  1956. // Convert from milliseconds to an Nt delta time.
  1957. //
  1958. WaitPipe->Timeout.QuadPart =
  1959. - (LONGLONG)UInt32x32To64( 10 * 1000, nTimeOut );
  1960. }
  1961. WaitPipe->TimeoutSpecified = TRUE;
  1962. }
  1963. WaitPipe->NameLength = PipeName.Length;
  1964. RtlCopyMemory(
  1965. WaitPipe->Name,
  1966. PipeName.Buffer,
  1967. PipeName.Length
  1968. );
  1969. RtlFreeUnicodeString(&OriginalPipeName);
  1970. Status = NtFsControlFile(Handle,
  1971. NULL,
  1972. NULL, // APC routine
  1973. NULL, // APC Context
  1974. &Iosb,
  1975. FSCTL_PIPE_WAIT,// IoControlCode
  1976. WaitPipe, // Buffer for data to the FS
  1977. WaitPipeLength,
  1978. NULL, // OutputBuffer for data from the FS
  1979. 0 // OutputBuffer Length
  1980. );
  1981. RtlFreeHeap(RtlProcessHeap(),0,WaitPipe);
  1982. NtClose(Handle);
  1983. if (NT_SUCCESS( Status ) ) {
  1984. return TRUE;
  1985. }
  1986. else
  1987. {
  1988. BaseSetLastNTError(Status);
  1989. return FALSE;
  1990. }
  1991. }
  1992. BOOL
  1993. APIENTRY
  1994. PeekNamedPipe(
  1995. HANDLE hNamedPipe,
  1996. LPVOID lpBuffer,
  1997. DWORD nBufferSize,
  1998. LPDWORD lpBytesRead,
  1999. LPDWORD lpTotalBytesAvail,
  2000. LPDWORD lpBytesLeftThisMessage
  2001. )
  2002. /*++
  2003. Routine Description:
  2004. The PeekNamedPipe function copies a named pipe's data into a buffer for
  2005. preview without removing it. The results of a PeekNamedPipe are similar to
  2006. a ReadFile on the pipe except more information is returned, the function
  2007. never blocks and if the pipe handle is reading in message mode, a partial
  2008. message can be returned.
  2009. A partial message peek'd on a message mode pipe will return TRUE.
  2010. It is not an error if all of the pointers passed to this function are
  2011. null. However, there is no reason for calling it this way.
  2012. The NT peek call has the received data immediately after the state
  2013. information so this routine needs to allocate an intermediate buffer
  2014. large enough for the state information plus data.
  2015. Arguments:
  2016. hNamedPipe - Supplies a handle to a named pipe.
  2017. lpBuffer - If non-null, pointer to buffer to read data into.
  2018. nBufferSize - Size of input buffer, in bytes. (Ignored if lpBuffer
  2019. is null.)
  2020. lpBytesRead - If non-null, this points to a DWORD which will be set
  2021. with the number of bytes actually read.
  2022. lpTotalBytesAvail - If non-null, this points to a DWORD which receives
  2023. a value giving the number of bytes that were available to be read.
  2024. lpBytesLeftThisMessage - If non-null, this points to a DWORD which
  2025. will be set to the number of bytes left in this message. (This will
  2026. be zero for a byte-stream pipe.)
  2027. Return Value:
  2028. TRUE -- The operation was successful.
  2029. FALSE -- The operation failed. Extended error status is available using
  2030. GetLastError.
  2031. --*/
  2032. {
  2033. IO_STATUS_BLOCK Iosb;
  2034. NTSTATUS Status;
  2035. PFILE_PIPE_PEEK_BUFFER PeekBuffer;
  2036. DWORD IOLength;
  2037. // Allocate enough for the users data and FILE_PIPE_PEEK_BUFFER
  2038. IOLength = nBufferSize + FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]);
  2039. PeekBuffer = (PFILE_PIPE_PEEK_BUFFER)
  2040. RtlAllocateHeap(RtlProcessHeap(), 0, IOLength);
  2041. if (PeekBuffer == NULL) {
  2042. BaseSetLastNTError (STATUS_INSUFFICIENT_RESOURCES);
  2043. return FALSE;
  2044. }
  2045. __try {
  2046. Status = NtFsControlFile(hNamedPipe,
  2047. NULL,
  2048. NULL, // APC routine
  2049. NULL, // APC Context
  2050. &Iosb, // I/O Status block
  2051. FSCTL_PIPE_PEEK,// IoControlCode
  2052. NULL, // Buffer for data to the FS
  2053. 0, // Length.
  2054. PeekBuffer, // OutputBuffer for data from the FS
  2055. IOLength // OutputBuffer Length
  2056. );
  2057. if ( Status == STATUS_PENDING) {
  2058. // Operation must complete before return & IoStatusBlock destroyed
  2059. Status = NtWaitForSingleObject( hNamedPipe, FALSE, NULL );
  2060. if ( NT_SUCCESS(Status)) {
  2061. Status = Iosb.Status;
  2062. }
  2063. }
  2064. //
  2065. // Buffer overflow simply means that lpBytesLeftThisMessage != 0
  2066. //
  2067. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  2068. Status = STATUS_SUCCESS;
  2069. }
  2070. //
  2071. // Peek is complete, package up data for caller ensuring that
  2072. // the PeekBuffer is deleted even if an invalid pointer was given.
  2073. //
  2074. if ( NT_SUCCESS(Status)) {
  2075. __try {
  2076. if ( ARGUMENT_PRESENT( lpTotalBytesAvail ) ) {
  2077. *lpTotalBytesAvail = PeekBuffer->ReadDataAvailable;
  2078. }
  2079. if ( ARGUMENT_PRESENT( lpBytesRead ) ) {
  2080. *lpBytesRead = (ULONG)(Iosb.Information - FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
  2081. }
  2082. if ( ARGUMENT_PRESENT( lpBytesLeftThisMessage ) ) {
  2083. *lpBytesLeftThisMessage =
  2084. PeekBuffer->MessageLength -
  2085. (ULONG)(Iosb.Information - FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
  2086. }
  2087. if ( ARGUMENT_PRESENT( lpBuffer ) ) {
  2088. RtlCopyMemory(
  2089. lpBuffer,
  2090. PeekBuffer->Data,
  2091. Iosb.Information - FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
  2092. }
  2093. }
  2094. __except (EXCEPTION_EXECUTE_HANDLER) {
  2095. Status = STATUS_ACCESS_VIOLATION;
  2096. }
  2097. }
  2098. }
  2099. __finally {
  2100. if ( PeekBuffer != NULL ) {
  2101. RtlFreeHeap(RtlProcessHeap(),0,PeekBuffer);
  2102. }
  2103. }
  2104. if ( NT_SUCCESS(Status) ) {
  2105. return TRUE;
  2106. }
  2107. else {
  2108. BaseSetLastNTError(Status);
  2109. return FALSE;
  2110. }
  2111. }
  2112. DWORD
  2113. WaitForSingleObject(
  2114. HANDLE hHandle,
  2115. DWORD dwMilliseconds
  2116. )
  2117. /*++
  2118. Routine Description:
  2119. A wait operation on a waitable object is accomplished with the
  2120. WaitForSingleObject function.
  2121. Waiting on an object checks the current state of the object. If the
  2122. current state of the object allows continued execution, any
  2123. adjustments to the object state are made (for example, decrementing
  2124. the semaphore count for a semaphore object) and the thread continues
  2125. execution. If the current state of the object does not allow
  2126. continued execution, the thread is placed into the wait state
  2127. pending the change of the object's state or time-out.
  2128. Arguments:
  2129. hHandle - An open handle to a waitable object. The handle must have
  2130. SYNCHRONIZE access to the object.
  2131. dwMilliseconds - A time-out value that specifies the relative time,
  2132. in milliseconds, over which the wait is to be completed. A
  2133. timeout value of 0 specified that the wait is to timeout
  2134. immediately. This allows an application to test an object to
  2135. determine if it is in the signaled state. A timeout value of -1
  2136. specifies an infinite timeout period.
  2137. Return Value:
  2138. WAIT_TIME_OUT - Indicates that the wait was terminated due to the
  2139. TimeOut conditions.
  2140. 0 - indicates the specified object attained a Signaled
  2141. state thus completing the wait.
  2142. WAIT_ABANDONED - indicates the specified object attained a Signaled
  2143. state but was abandoned.
  2144. --*/
  2145. {
  2146. return WaitForSingleObjectEx(hHandle,dwMilliseconds,FALSE);
  2147. }
  2148. DWORD
  2149. APIENTRY
  2150. WaitForSingleObjectEx(
  2151. HANDLE hHandle,
  2152. DWORD dwMilliseconds,
  2153. BOOL bAlertable
  2154. )
  2155. /*++
  2156. Routine Description:
  2157. A wait operation on a waitable object is accomplished with the
  2158. WaitForSingleObjectEx function.
  2159. Waiting on an object checks the current state of the object. If the
  2160. current state of the object allows continued execution, any
  2161. adjustments to the object state are made (for example, decrementing
  2162. the semaphore count for a semaphore object) and the thread continues
  2163. execution. If the current state of the object does not allow
  2164. continued execution, the thread is placed into the wait state
  2165. pending the change of the object's state or time-out.
  2166. If the bAlertable parameter is FALSE, the only way the wait
  2167. terminates is because the specified timeout period expires, or
  2168. because the specified object entered the signaled state. If the
  2169. bAlertable parameter is TRUE, then the wait can return due to any
  2170. one of the above wait termination conditions, or because an I/O
  2171. completion callback terminated the wait early (return value of
  2172. WAIT_IO_COMPLETION).
  2173. Arguments:
  2174. hHandle - An open handle to a waitable object. The handle must have
  2175. SYNCHRONIZE access to the object.
  2176. dwMilliseconds - A time-out value that specifies the relative time,
  2177. in milliseconds, over which the wait is to be completed. A
  2178. timeout value of 0 specified that the wait is to timeout
  2179. immediately. This allows an application to test an object to
  2180. determine if it is in the signaled state. A timeout value of
  2181. 0xffffffff specifies an infinite timeout period.
  2182. bAlertable - Supplies a flag that controls whether or not the
  2183. wait may terminate early due to an I/O completion callback.
  2184. A value of TRUE allows this API to complete early due to an I/O
  2185. completion callback. A value of FALSE will not allow I/O
  2186. completion callbacks to terminate this call early.
  2187. Return Value:
  2188. WAIT_TIME_OUT - Indicates that the wait was terminated due to the
  2189. TimeOut conditions.
  2190. 0 - indicates the specified object attained a Signaled
  2191. state thus completing the wait.
  2192. 0xffffffff - The wait terminated due to an error. GetLastError may be
  2193. used to get additional error information.
  2194. WAIT_ABANDONED - indicates the specified object attained a Signaled
  2195. state but was abandoned.
  2196. WAIT_IO_COMPLETION - The wait terminated due to one or more I/O
  2197. completion callbacks.
  2198. --*/
  2199. {
  2200. NTSTATUS Status;
  2201. LARGE_INTEGER TimeOut;
  2202. PLARGE_INTEGER pTimeOut;
  2203. PPEB Peb;
  2204. RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME Frame = { sizeof(Frame), RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER };
  2205. RtlActivateActivationContextUnsafeFast(&Frame, NULL); // make the process default activation context active so that APCs are delivered under it
  2206. __try {
  2207. if (dwMilliseconds == INFINITE)
  2208. {
  2209. pTimeOut = NULL;
  2210. }
  2211. else
  2212. {
  2213. Win32ToNtTimeout(dwMilliseconds, &TimeOut);
  2214. pTimeOut = &TimeOut;
  2215. }
  2216. rewait:
  2217. Status = NtWaitForSingleObject(hHandle,(BOOLEAN)bAlertable,pTimeOut);
  2218. if ( !NT_SUCCESS(Status) ) {
  2219. BaseSetLastNTError(Status);
  2220. Status = (NTSTATUS)0xffffffff;
  2221. }
  2222. else {
  2223. if ( bAlertable && Status == STATUS_ALERTED ) {
  2224. goto rewait;
  2225. }
  2226. }
  2227. } __finally {
  2228. RtlDeactivateActivationContextUnsafeFast(&Frame);
  2229. }
  2230. return (DWORD)Status;
  2231. }
  2232. DWORD
  2233. WaitForMultipleObjects(
  2234. DWORD nCount,
  2235. CONST HANDLE *lpHandles,
  2236. BOOL bWaitAll,
  2237. DWORD dwMilliseconds
  2238. )
  2239. /*++
  2240. Routine Description:
  2241. A wait operation on multiple waitable objects (up to
  2242. MAXIMUM_WAIT_OBJECTS) is accomplished with the WaitForMultipleObjects
  2243. function.
  2244. Arguments:
  2245. nCount - A count of the number of objects that are to be waited on.
  2246. lpHandles - An array of object handles. Each handle must have
  2247. SYNCHRONIZE access to the associated object.
  2248. bWaitAll - A flag that supplies the wait type. A value of TRUE
  2249. indicates a "wait all". A value of false indicates a "wait
  2250. any".
  2251. dwMilliseconds - A time-out value that specifies the relative time,
  2252. in milliseconds, over which the wait is to be completed. A
  2253. timeout value of 0 specified that the wait is to timeout
  2254. immediately. This allows an application to test an object to
  2255. determine if it is in the signaled state. A timeout value of -1
  2256. specifies an infinite timeout period.
  2257. Return Value:
  2258. WAIT_TIME_OUT - indicates that the wait was terminated due to the
  2259. TimeOut conditions.
  2260. 0 to MAXIMUM_WAIT_OBJECTS-1, indicates, in the case of wait for any
  2261. object, the object number which satisfied the wait. In the case
  2262. of wait for all objects, the value only indicates that the wait
  2263. was completed successfully.
  2264. WAIT_ABANDONED_0 to (WAIT_ABANDONED_0)+(MAXIMUM_WAIT_OBJECTS - 1),
  2265. indicates, in the case of wait for any object, the object number
  2266. which satisfied the event, and that the object which satisfied
  2267. the event was abandoned. In the case of wait for all objects,
  2268. the value indicates that the wait was completed successfully and
  2269. at least one of the objects was abandoned.
  2270. --*/
  2271. {
  2272. return WaitForMultipleObjectsEx(nCount,lpHandles,bWaitAll,dwMilliseconds,FALSE);
  2273. }
  2274. DWORD
  2275. APIENTRY
  2276. WaitForMultipleObjectsEx(
  2277. DWORD nCount,
  2278. CONST HANDLE *lpHandles,
  2279. BOOL bWaitAll,
  2280. DWORD dwMilliseconds,
  2281. BOOL bAlertable
  2282. )
  2283. /*++
  2284. Routine Description:
  2285. A wait operation on multiple waitable objects (up to
  2286. MAXIMUM_WAIT_OBJECTS) is accomplished with the
  2287. WaitForMultipleObjects function.
  2288. This API can be used to wait on any of the specified objects to
  2289. enter the signaled state, or all of the objects to enter the
  2290. signaled state.
  2291. If the bAlertable parameter is FALSE, the only way the wait
  2292. terminates is because the specified timeout period expires, or
  2293. because the specified objects entered the signaled state. If the
  2294. bAlertable parameter is TRUE, then the wait can return due to any one of
  2295. the above wait termination conditions, or because an I/O completion
  2296. callback terminated the wait early (return value of
  2297. WAIT_IO_COMPLETION).
  2298. Arguments:
  2299. nCount - A count of the number of objects that are to be waited on.
  2300. lpHandles - An array of object handles. Each handle must have
  2301. SYNCHRONIZE access to the associated object.
  2302. bWaitAll - A flag that supplies the wait type. A value of TRUE
  2303. indicates a "wait all". A value of false indicates a "wait
  2304. any".
  2305. dwMilliseconds - A time-out value that specifies the relative time,
  2306. in milliseconds, over which the wait is to be completed. A
  2307. timeout value of 0 specified that the wait is to timeout
  2308. immediately. This allows an application to test an object to
  2309. determine if it is in the signaled state. A timeout value of
  2310. 0xffffffff specifies an infinite timeout period.
  2311. bAlertable - Supplies a flag that controls whether or not the
  2312. wait may terminate early due to an I/O completion callback.
  2313. A value of TRUE allows this API to complete early due to an I/O
  2314. completion callback. A value of FALSE will not allow I/O
  2315. completion callbacks to terminate this call early.
  2316. Return Value:
  2317. WAIT_TIME_OUT - indicates that the wait was terminated due to the
  2318. TimeOut conditions.
  2319. 0 to MAXIMUM_WAIT_OBJECTS-1, indicates, in the case of wait for any
  2320. object, the object number which satisfied the wait. In the case
  2321. of wait for all objects, the value only indicates that the wait
  2322. was completed successfully.
  2323. 0xffffffff - The wait terminated due to an error. GetLastError may be
  2324. used to get additional error information.
  2325. WAIT_ABANDONED_0 to (WAIT_ABANDONED_0)+(MAXIMUM_WAIT_OBJECTS - 1),
  2326. indicates, in the case of wait for any object, the object number
  2327. which satisfied the event, and that the object which satisfied
  2328. the event was abandoned. In the case of wait for all objects,
  2329. the value indicates that the wait was completed successfully and
  2330. at least one of the objects was abandoned.
  2331. WAIT_IO_COMPLETION - The wait terminated due to one or more I/O
  2332. completion callbacks.
  2333. --*/
  2334. {
  2335. NTSTATUS Status;
  2336. LARGE_INTEGER TimeOut;
  2337. PLARGE_INTEGER pTimeOut;
  2338. DWORD i;
  2339. LPHANDLE HandleArray;
  2340. HANDLE Handles[ 8 ];
  2341. PPEB Peb;
  2342. RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME Frame = { sizeof(Frame), RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER };
  2343. if (nCount > 8) {
  2344. BaseSetLastNTError(STATUS_NO_MEMORY);
  2345. return 0xffffffff;
  2346. }
  2347. RtlActivateActivationContextUnsafeFast(&Frame, NULL); // make the process default activation context active so that APCs are delivered under it
  2348. __try {
  2349. HandleArray = Handles;
  2350. RtlCopyMemory(HandleArray,(LPVOID)lpHandles,nCount*sizeof(HANDLE));
  2351. Peb = NtCurrentPeb();
  2352. if (dwMilliseconds == INFINITE)
  2353. {
  2354. pTimeOut = NULL;
  2355. }
  2356. else
  2357. {
  2358. Win32ToNtTimeout(dwMilliseconds, &TimeOut);
  2359. pTimeOut = &TimeOut;
  2360. }
  2361. rewait:
  2362. Status = NtWaitForMultipleObjects(
  2363. (CHAR)nCount,
  2364. HandleArray,
  2365. bWaitAll ? WaitAll : WaitAny,
  2366. (BOOLEAN)bAlertable,
  2367. pTimeOut
  2368. );
  2369. if ( !NT_SUCCESS(Status) ) {
  2370. BaseSetLastNTError(Status);
  2371. Status = (NTSTATUS)0xffffffff;
  2372. }
  2373. else {
  2374. if ( bAlertable && Status == STATUS_ALERTED ) {
  2375. goto rewait;
  2376. }
  2377. }
  2378. if (HandleArray != Handles) {
  2379. RtlFreeHeap(RtlProcessHeap(), 0, HandleArray);
  2380. }
  2381. } __finally {
  2382. RtlDeactivateActivationContextUnsafeFast(&Frame);
  2383. }
  2384. return (DWORD)Status;
  2385. }
  2386. HANDLE
  2387. APIENTRY
  2388. CreateEventA(
  2389. LPSECURITY_ATTRIBUTES lpEventAttributes,
  2390. BOOL bManualReset,
  2391. BOOL bInitialState,
  2392. LPCSTR lpName
  2393. )
  2394. /*++
  2395. Routine Description:
  2396. ANSI thunk to CreateEventW
  2397. --*/
  2398. {
  2399. PUNICODE_STRING Unicode;
  2400. ANSI_STRING AnsiString;
  2401. NTSTATUS Status;
  2402. LPCWSTR NameBuffer;
  2403. NameBuffer = NULL;
  2404. if ( ARGUMENT_PRESENT(lpName) ) {
  2405. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  2406. RtlInitAnsiString(&AnsiString,lpName);
  2407. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  2408. if ( !NT_SUCCESS(Status) ) {
  2409. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  2410. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  2411. }
  2412. else {
  2413. BaseSetLastNTError(Status);
  2414. }
  2415. return NULL;
  2416. }
  2417. NameBuffer = (LPCWSTR)Unicode->Buffer;
  2418. }
  2419. return CreateEventW(
  2420. lpEventAttributes,
  2421. bManualReset,
  2422. bInitialState,
  2423. NameBuffer
  2424. );
  2425. }
  2426. HANDLE
  2427. APIENTRY
  2428. CreateEventW(
  2429. LPSECURITY_ATTRIBUTES lpEventAttributes,
  2430. BOOL bManualReset,
  2431. BOOL bInitialState,
  2432. LPCWSTR lpName
  2433. )
  2434. /*++
  2435. Routine Description:
  2436. An event object is created and a handle opened for access to the
  2437. object with the CreateEvent function.
  2438. The CreateEvent function creates an event object with the specified
  2439. initial state. If an event is in the Signaled state (TRUE), a wait
  2440. operation on the event does not block. If the event is in the Not-
  2441. Signaled state (FALSE), a wait operation on the event blocks until
  2442. the specified event attains a state of Signaled, or the timeout
  2443. value is exceeded.
  2444. In addition to the STANDARD_RIGHTS_REQUIRED access flags, the following
  2445. object type specific access flags are valid for event objects:
  2446. - EVENT_MODIFY_STATE - Modify state access (set and reset) to
  2447. the event is desired.
  2448. - SYNCHRONIZE - Synchronization access (wait) to the event is
  2449. desired.
  2450. - EVENT_ALL_ACCESS - This set of access flags specifies all of
  2451. the possible access flags for an event object.
  2452. Arguments:
  2453. lpEventAttributes - An optional parameter that may be used to
  2454. specify the attributes of the new event. If the parameter is
  2455. not specified, then the event is created without a security
  2456. descriptor, and the resulting handle is not inherited on process
  2457. creation.
  2458. bManualReset - Supplies a flag which if TRUE specifies that the
  2459. event must be manually reset. If the value is FALSE, then after
  2460. releasing a single waiter, the system automaticaly resets the
  2461. event.
  2462. bInitialState - The initial state of the event object, one of TRUE
  2463. or FALSE. If the InitialState is specified as TRUE, the event's
  2464. current state value is set to one, otherwise it is set to zero.
  2465. lpName - Optional unicode name of event
  2466. Return Value:
  2467. NON-NULL - Returns a handle to the new event. The handle has full
  2468. access to the new event and may be used in any API that requires
  2469. a handle to an event object.
  2470. FALSE/NULL - The operation failed. Extended error status is available
  2471. using GetLastError.
  2472. --*/
  2473. {
  2474. NTSTATUS Status;
  2475. OBJECT_ATTRIBUTES Obja;
  2476. POBJECT_ATTRIBUTES pObja;
  2477. HANDLE Handle;
  2478. UNICODE_STRING ObjectName;
  2479. PWCHAR pstrNewObjName = NULL;
  2480. if (lpName != NULL || lpEventAttributes != NULL)
  2481. {
  2482. return FALSE;
  2483. }
  2484. pObja = NULL;
  2485. Status = NtCreateEvent(
  2486. &Handle,
  2487. EVENT_ALL_ACCESS,
  2488. pObja,
  2489. bManualReset ? NotificationEvent : SynchronizationEvent,
  2490. (BOOLEAN)bInitialState
  2491. );
  2492. if (pstrNewObjName) {
  2493. RtlFreeHeap(RtlProcessHeap(), 0, pstrNewObjName);
  2494. }
  2495. if ( NT_SUCCESS(Status) ) {
  2496. if ( Status == STATUS_OBJECT_NAME_EXISTS ) {
  2497. SetLastError(ERROR_ALREADY_EXISTS);
  2498. }
  2499. else {
  2500. SetLastError(0);
  2501. }
  2502. return Handle;
  2503. }
  2504. else {
  2505. BaseSetLastNTError(Status);
  2506. return NULL;
  2507. }
  2508. }
  2509. BOOL
  2510. SetEvent(
  2511. HANDLE hEvent
  2512. )
  2513. /*++
  2514. Routine Description:
  2515. An event can be set to the signaled state (TRUE) with the SetEvent
  2516. function.
  2517. Setting the event causes the event to attain a state of Signaled,
  2518. which releases all currently waiting threads (for manual reset
  2519. events), or a single waiting thread (for automatic reset events).
  2520. Arguments:
  2521. hEvent - Supplies an open handle to an event object. The
  2522. handle must have EVENT_MODIFY_STATE access to the event.
  2523. Return Value:
  2524. TRUE - The operation was successful
  2525. FALSE/NULL - The operation failed. Extended error status is available
  2526. using GetLastError.
  2527. --*/
  2528. {
  2529. NTSTATUS Status;
  2530. Status = NtSetEvent(hEvent,NULL);
  2531. if ( NT_SUCCESS(Status) ) {
  2532. return TRUE;
  2533. }
  2534. else {
  2535. BaseSetLastNTError(Status);
  2536. return FALSE;
  2537. }
  2538. }
  2539. BOOL
  2540. ResetEvent(
  2541. HANDLE hEvent
  2542. )
  2543. /*++
  2544. Routine Description:
  2545. The state of an event is set to the Not-Signaled state (FALSE) using
  2546. the ClearEvent function.
  2547. Once the event attains a state of Not-Signaled, any threads which
  2548. wait on the event block, awaiting the event to become Signaled. The
  2549. reset event service sets the event count to zero for the state of
  2550. the event.
  2551. Arguments:
  2552. hEvent - Supplies an open handle to an event object. The
  2553. handle must have EVENT_MODIFY_STATE access to the event.
  2554. Return Value:
  2555. TRUE - The operation was successful
  2556. FALSE/NULL - The operation failed. Extended error status is available
  2557. using GetLastError.
  2558. --*/
  2559. {
  2560. NTSTATUS Status;
  2561. Status = NtClearEvent(hEvent);
  2562. if ( NT_SUCCESS(Status) ) {
  2563. return TRUE;
  2564. }
  2565. else {
  2566. BaseSetLastNTError(Status);
  2567. return FALSE;
  2568. }
  2569. }
  2570. BOOL
  2571. WINAPI
  2572. GetOverlappedResult(
  2573. HANDLE hFile,
  2574. LPOVERLAPPED lpOverlapped,
  2575. LPDWORD lpNumberOfBytesTransferred,
  2576. BOOL bWait
  2577. )
  2578. /*++
  2579. Routine Description:
  2580. The GetOverlappedResult function returns the result of the last
  2581. operation that used lpOverlapped and returned ERROR_IO_PENDING.
  2582. Arguments:
  2583. hFile - Supplies the open handle to the file that the overlapped
  2584. structure lpOverlapped was supplied to ReadFile, WriteFile,
  2585. ConnectNamedPipe, WaitNamedPipe or TransactNamedPipe.
  2586. lpOverlapped - Points to an OVERLAPPED structure previously supplied to
  2587. ReadFile, WriteFile, ConnectNamedPipe, WaitNamedPipe or
  2588. TransactNamedPipe.
  2589. lpNumberOfBytesTransferred - Returns the number of bytes transferred
  2590. by the operation.
  2591. bWait - A boolean value that affects the behavior when the operation
  2592. is still in progress. If TRUE and the operation is still in progress,
  2593. GetOverlappedResult will wait for the operation to complete before
  2594. returning. If FALSE and the operation is incomplete,
  2595. GetOverlappedResult will return FALSE. In this case the extended
  2596. error information available from the GetLastError function will be
  2597. set to ERROR_IO_INCOMPLETE.
  2598. Return Value:
  2599. TRUE -- The operation was successful, the pipe is in the
  2600. connected state.
  2601. FALSE -- The operation failed. Extended error status is available using
  2602. GetLastError.
  2603. --*/
  2604. {
  2605. DWORD WaitReturn;
  2606. //
  2607. // Did caller specify an event to the original operation or was the
  2608. // default (file handle) used?
  2609. //
  2610. if (lpOverlapped->Internal == (DWORD)STATUS_PENDING ) {
  2611. if ( bWait ) {
  2612. WaitReturn = WaitForSingleObject(
  2613. ( lpOverlapped->hEvent != NULL ) ?
  2614. lpOverlapped->hEvent : hFile,
  2615. INFINITE
  2616. );
  2617. }
  2618. else {
  2619. WaitReturn = WAIT_TIMEOUT;
  2620. }
  2621. if ( WaitReturn == WAIT_TIMEOUT ) {
  2622. // !bWait and event in not signalled state
  2623. SetLastError( ERROR_IO_INCOMPLETE );
  2624. return FALSE;
  2625. }
  2626. if ( WaitReturn != 0 ) {
  2627. return FALSE; // WaitForSingleObject calls BaseSetLastError
  2628. }
  2629. }
  2630. *lpNumberOfBytesTransferred = (DWORD)lpOverlapped->InternalHigh;
  2631. if ( NT_SUCCESS((NTSTATUS)lpOverlapped->Internal) ){
  2632. return TRUE;
  2633. }
  2634. else {
  2635. BaseSetLastNTError( (NTSTATUS)lpOverlapped->Internal );
  2636. return FALSE;
  2637. }
  2638. }
  2639. BOOL
  2640. WINAPI
  2641. CancelIo(
  2642. HANDLE hFile
  2643. )
  2644. /*++
  2645. Routine Description:
  2646. This routine cancels all of the outstanding I/O for the specified handle
  2647. for the specified file.
  2648. Arguments:
  2649. hFile - Supplies the handle to the file whose pending I/O is to be
  2650. canceled.
  2651. Return Value:
  2652. TRUE -- The operation was successful.
  2653. FALSE -- The operation failed. Extended error status is available using
  2654. GetLastError.
  2655. --*/
  2656. {
  2657. NTSTATUS Status;
  2658. IO_STATUS_BLOCK IoStatusBlock;
  2659. //
  2660. // Simply cancel the I/O for the specified file.
  2661. //
  2662. Status = NtCancelIoFile(hFile, &IoStatusBlock);
  2663. if ( NT_SUCCESS(Status) ) {
  2664. return TRUE;
  2665. }
  2666. else {
  2667. BaseSetLastNTError(Status);
  2668. return FALSE;
  2669. }
  2670. }
  2671. BOOL
  2672. ClearCommError(
  2673. HANDLE hFile,
  2674. LPDWORD lpErrors,
  2675. LPCOMSTAT lpStat
  2676. )
  2677. /*++
  2678. Routine Description:
  2679. In case of a communications error, such as a buffer overrun or
  2680. framing error, the communications software will abort all
  2681. read and write operations on the communication port. No further
  2682. read or write operations will be accepted until this function
  2683. is called.
  2684. Arguments:
  2685. hFile - Specifies the communication device to be adjusted.
  2686. lpErrors - Points to the DWORD that is to receive the mask of the
  2687. error that occured.
  2688. lpStat - Points to the COMMSTAT structure that is to receive
  2689. the device status. The structure contains information
  2690. about the communications device.
  2691. Return Value:
  2692. The return value is TRUE if the function is successful or FALSE
  2693. if an error occurs.
  2694. --*/
  2695. {
  2696. NTSTATUS Status;
  2697. HANDLE SyncEvent;
  2698. IO_STATUS_BLOCK Iosb;
  2699. SERIAL_STATUS LocalStat;
  2700. RtlZeroMemory(&LocalStat, sizeof(SERIAL_STATUS));
  2701. if (!(SyncEvent = CreateEvent(
  2702. NULL,
  2703. TRUE,
  2704. FALSE,
  2705. NULL
  2706. ))) {
  2707. return FALSE;
  2708. }
  2709. Status = NtDeviceIoControlFile(
  2710. hFile,
  2711. SyncEvent,
  2712. NULL,
  2713. NULL,
  2714. &Iosb,
  2715. IOCTL_SERIAL_GET_COMMSTATUS,
  2716. NULL,
  2717. 0,
  2718. &LocalStat,
  2719. sizeof(LocalStat)
  2720. );
  2721. if ( Status == STATUS_PENDING) {
  2722. // Operation must complete before return & IoStatusBlock destroyed
  2723. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  2724. if ( NT_SUCCESS(Status)) {
  2725. Status = Iosb.Status;
  2726. }
  2727. }
  2728. if (NT_ERROR(Status)) {
  2729. CloseHandle(SyncEvent);
  2730. BaseSetLastNTError(Status);
  2731. return FALSE;
  2732. }
  2733. if (lpStat) {
  2734. //
  2735. // All is well up to this point. Translate the NT values
  2736. // into win32 values.
  2737. //
  2738. if (LocalStat.HoldReasons & SERIAL_TX_WAITING_FOR_CTS) {
  2739. lpStat->fCtsHold = TRUE;
  2740. } else {
  2741. lpStat->fCtsHold = FALSE;
  2742. }
  2743. if (LocalStat.HoldReasons & SERIAL_TX_WAITING_FOR_DSR) {
  2744. lpStat->fDsrHold = TRUE;
  2745. } else {
  2746. lpStat->fDsrHold = FALSE;
  2747. }
  2748. if (LocalStat.HoldReasons & SERIAL_TX_WAITING_FOR_DCD) {
  2749. lpStat->fRlsdHold = TRUE;
  2750. } else {
  2751. lpStat->fRlsdHold = FALSE;
  2752. }
  2753. if (LocalStat.HoldReasons & SERIAL_TX_WAITING_FOR_XON) {
  2754. lpStat->fXoffHold = TRUE;
  2755. } else {
  2756. lpStat->fXoffHold = FALSE;
  2757. }
  2758. if (LocalStat.HoldReasons & SERIAL_TX_WAITING_XOFF_SENT) {
  2759. lpStat->fXoffSent = TRUE;
  2760. } else {
  2761. lpStat->fXoffSent = FALSE;
  2762. }
  2763. lpStat->fEof = LocalStat.EofReceived;
  2764. lpStat->fTxim = LocalStat.WaitForImmediate;
  2765. lpStat->cbInQue = LocalStat.AmountInInQueue;
  2766. lpStat->cbOutQue = LocalStat.AmountInOutQueue;
  2767. }
  2768. if (lpErrors) {
  2769. *lpErrors = 0;
  2770. if (LocalStat.Errors & SERIAL_ERROR_BREAK) {
  2771. *lpErrors = *lpErrors | CE_BREAK;
  2772. }
  2773. if (LocalStat.Errors & SERIAL_ERROR_FRAMING) {
  2774. *lpErrors = *lpErrors | CE_FRAME;
  2775. }
  2776. if (LocalStat.Errors & SERIAL_ERROR_OVERRUN) {
  2777. *lpErrors = *lpErrors | CE_OVERRUN;
  2778. }
  2779. if (LocalStat.Errors & SERIAL_ERROR_QUEUEOVERRUN) {
  2780. *lpErrors = *lpErrors | CE_RXOVER;
  2781. }
  2782. if (LocalStat.Errors & SERIAL_ERROR_PARITY) {
  2783. *lpErrors = *lpErrors | CE_RXPARITY;
  2784. }
  2785. }
  2786. CloseHandle(SyncEvent);
  2787. return TRUE;
  2788. }
  2789. BOOL
  2790. SetupComm(
  2791. HANDLE hFile,
  2792. DWORD dwInQueue,
  2793. DWORD dwOutQueue
  2794. )
  2795. /*++
  2796. Routine Description:
  2797. The communication device is not initialized until SetupComm is
  2798. called. This function allocates space for receive and transmit
  2799. queues. These queues are used by the interrupt-driven transmit/
  2800. receive software and are internal to the provider.
  2801. Arguments:
  2802. hFile - Specifies the communication device to receive the settings.
  2803. The CreateFile function returns this value.
  2804. dwInQueue - Specifies the recommended size of the provider's
  2805. internal receive queue in bytes. This value must be
  2806. even. A value of -1 indicates that the default should
  2807. be used.
  2808. dwOutQueue - Specifies the recommended size of the provider's
  2809. internal transmit queue in bytes. This value must be
  2810. even. A value of -1 indicates that the default should
  2811. be used.
  2812. Return Value:
  2813. The return value is TRUE if the function is successful or FALSE
  2814. if an error occurs.
  2815. --*/
  2816. {
  2817. NTSTATUS Status;
  2818. HANDLE SyncEvent;
  2819. IO_STATUS_BLOCK Iosb;
  2820. SERIAL_QUEUE_SIZE NewSizes = {0};
  2821. //
  2822. // Make sure that the sizes are even.
  2823. //
  2824. if (dwOutQueue != ((DWORD)-1)) {
  2825. if (((dwOutQueue/2)*2) != dwOutQueue) {
  2826. SetLastError(ERROR_INVALID_DATA);
  2827. return FALSE;
  2828. }
  2829. }
  2830. if (dwInQueue != ((DWORD)-1)) {
  2831. if (((dwInQueue/2)*2) != dwInQueue) {
  2832. SetLastError(ERROR_INVALID_DATA);
  2833. return FALSE;
  2834. }
  2835. }
  2836. NewSizes.InSize = dwInQueue;
  2837. NewSizes.OutSize = dwOutQueue;
  2838. if (!(SyncEvent = CreateEvent(
  2839. NULL,
  2840. TRUE,
  2841. FALSE,
  2842. NULL
  2843. ))) {
  2844. return FALSE;
  2845. }
  2846. Status = NtDeviceIoControlFile(
  2847. hFile,
  2848. SyncEvent,
  2849. NULL,
  2850. NULL,
  2851. &Iosb,
  2852. IOCTL_SERIAL_SET_QUEUE_SIZE,
  2853. &NewSizes,
  2854. sizeof(SERIAL_QUEUE_SIZE),
  2855. NULL,
  2856. 0
  2857. );
  2858. if ( Status == STATUS_PENDING) {
  2859. // Operation must complete before return & IoStatusBlock destroyed
  2860. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  2861. if ( NT_SUCCESS(Status)) {
  2862. Status = Iosb.Status;
  2863. }
  2864. }
  2865. if (NT_ERROR(Status)) {
  2866. CloseHandle(SyncEvent);
  2867. BaseSetLastNTError(Status);
  2868. return FALSE;
  2869. }
  2870. CloseHandle(SyncEvent);
  2871. return TRUE;
  2872. }
  2873. BOOL
  2874. GetCommState(
  2875. HANDLE hFile,
  2876. LPDCB lpDCB
  2877. )
  2878. /*++
  2879. Routine Description:
  2880. This function fills the buffer pointed to by the lpDCB parameter with
  2881. the device control block of the communication device specified by hFile
  2882. parameter.
  2883. Arguments:
  2884. hFile - Specifies the communication device to be examined.
  2885. The CreateFile function returns this value.
  2886. lpDCB - Points to the DCB data structure that is to receive the current
  2887. device control block. The structure defines the control settings
  2888. for the device.
  2889. Return Value:
  2890. The return value is TRUE if the function is successful or FALSE
  2891. if an error occurs.
  2892. --*/
  2893. {
  2894. SERIAL_BAUD_RATE LocalBaud;
  2895. SERIAL_LINE_CONTROL LineControl;
  2896. SERIAL_CHARS Chars;
  2897. SERIAL_HANDFLOW HandFlow;
  2898. IO_STATUS_BLOCK Iosb;
  2899. NTSTATUS Status;
  2900. //
  2901. // Given the possiblity that the app may be doing asynchronous
  2902. // io we need an event to wait on.
  2903. //
  2904. // We need to make sure that any exit to this routine closes this
  2905. // event handle.
  2906. //
  2907. HANDLE SyncEvent;
  2908. //
  2909. // Make sure the windows mapping is the same as the NT mapping.
  2910. //
  2911. ASSERT((ONESTOPBIT == STOP_BIT_1) &&
  2912. (ONE5STOPBITS == STOP_BITS_1_5) &&
  2913. (TWOSTOPBITS == STOP_BITS_2));
  2914. ASSERT((NOPARITY == NO_PARITY) &&
  2915. (ODDPARITY == ODD_PARITY) &&
  2916. (EVENPARITY == EVEN_PARITY) &&
  2917. (MARKPARITY == MARK_PARITY) &&
  2918. (SPACEPARITY == SPACE_PARITY));
  2919. //
  2920. // Zero out the dcb. This might create an access violation
  2921. // if it isn't big enough. Which is ok, since we would rather
  2922. // get it before we create the sync event.
  2923. //
  2924. RtlZeroMemory(lpDCB, sizeof(DCB));
  2925. lpDCB->DCBlength = sizeof(DCB);
  2926. lpDCB->fBinary = TRUE;
  2927. if (!(SyncEvent = CreateEvent(
  2928. NULL,
  2929. TRUE,
  2930. FALSE,
  2931. NULL
  2932. ))) {
  2933. return FALSE;
  2934. }
  2935. Status = NtDeviceIoControlFile(
  2936. hFile,
  2937. SyncEvent,
  2938. NULL,
  2939. NULL,
  2940. &Iosb,
  2941. IOCTL_SERIAL_GET_BAUD_RATE,
  2942. NULL,
  2943. 0,
  2944. &LocalBaud,
  2945. sizeof(LocalBaud)
  2946. );
  2947. if ( Status == STATUS_PENDING) {
  2948. // Operation must complete before return & IoStatusBlock destroyed
  2949. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  2950. if ( NT_SUCCESS(Status)) {
  2951. Status = Iosb.Status;
  2952. }
  2953. }
  2954. if (NT_ERROR(Status)) {
  2955. CloseHandle(SyncEvent);
  2956. BaseSetLastNTError(Status);
  2957. return FALSE;
  2958. }
  2959. lpDCB->BaudRate = LocalBaud.BaudRate;
  2960. Status = NtDeviceIoControlFile(
  2961. hFile,
  2962. SyncEvent,
  2963. NULL,
  2964. NULL,
  2965. &Iosb,
  2966. IOCTL_SERIAL_GET_LINE_CONTROL,
  2967. NULL,
  2968. 0,
  2969. &LineControl,
  2970. sizeof(LineControl)
  2971. );
  2972. if ( Status == STATUS_PENDING) {
  2973. // Operation must complete before return & IoStatusBlock destroyed
  2974. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  2975. if ( NT_SUCCESS(Status)) {
  2976. Status = Iosb.Status;
  2977. }
  2978. }
  2979. if (NT_ERROR(Status)) {
  2980. CloseHandle(SyncEvent);
  2981. BaseSetLastNTError(Status);
  2982. return FALSE;
  2983. }
  2984. lpDCB->Parity = LineControl.Parity;
  2985. lpDCB->ByteSize = LineControl.WordLength;
  2986. lpDCB->StopBits = LineControl.StopBits;
  2987. Status = NtDeviceIoControlFile(
  2988. hFile,
  2989. SyncEvent,
  2990. NULL,
  2991. NULL,
  2992. &Iosb,
  2993. IOCTL_SERIAL_GET_CHARS,
  2994. NULL,
  2995. 0,
  2996. &Chars,
  2997. sizeof(Chars)
  2998. );
  2999. if ( Status == STATUS_PENDING) {
  3000. // Operation must complete before return & IoStatusBlock destroyed
  3001. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  3002. if ( NT_SUCCESS(Status)) {
  3003. Status = Iosb.Status;
  3004. }
  3005. }
  3006. if (NT_ERROR(Status)) {
  3007. CloseHandle(SyncEvent);
  3008. BaseSetLastNTError(Status);
  3009. return FALSE;
  3010. }
  3011. lpDCB->XonChar = Chars.XonChar;
  3012. lpDCB->XoffChar = Chars.XoffChar;
  3013. lpDCB->ErrorChar = Chars.ErrorChar;
  3014. lpDCB->EofChar = Chars.EofChar;
  3015. lpDCB->EvtChar = Chars.EventChar;
  3016. Status = NtDeviceIoControlFile(
  3017. hFile,
  3018. SyncEvent,
  3019. NULL,
  3020. NULL,
  3021. &Iosb,
  3022. IOCTL_SERIAL_GET_HANDFLOW,
  3023. NULL,
  3024. 0,
  3025. &HandFlow,
  3026. sizeof(HandFlow)
  3027. );
  3028. if ( Status == STATUS_PENDING) {
  3029. // Operation must complete before return & IoStatusBlock destroyed
  3030. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  3031. if ( NT_SUCCESS(Status)) {
  3032. Status = Iosb.Status;
  3033. }
  3034. }
  3035. if (NT_ERROR(Status)) {
  3036. CloseHandle(SyncEvent);
  3037. BaseSetLastNTError(Status);
  3038. return FALSE;
  3039. }
  3040. if (HandFlow.ControlHandShake & SERIAL_CTS_HANDSHAKE) {
  3041. lpDCB->fOutxCtsFlow = TRUE;
  3042. }
  3043. if (HandFlow.ControlHandShake & SERIAL_DSR_HANDSHAKE) {
  3044. lpDCB->fOutxDsrFlow = TRUE;
  3045. }
  3046. if (HandFlow.FlowReplace & SERIAL_AUTO_TRANSMIT) {
  3047. lpDCB->fOutX = TRUE;
  3048. }
  3049. if (HandFlow.FlowReplace & SERIAL_AUTO_RECEIVE) {
  3050. lpDCB->fInX = TRUE;
  3051. }
  3052. if (HandFlow.FlowReplace & SERIAL_NULL_STRIPPING) {
  3053. lpDCB->fNull = TRUE;
  3054. }
  3055. if (HandFlow.FlowReplace & SERIAL_ERROR_CHAR) {
  3056. lpDCB->fErrorChar = TRUE;
  3057. }
  3058. if (HandFlow.FlowReplace & SERIAL_XOFF_CONTINUE) {
  3059. lpDCB->fTXContinueOnXoff = TRUE;
  3060. }
  3061. if (HandFlow.ControlHandShake & SERIAL_ERROR_ABORT) {
  3062. lpDCB->fAbortOnError = TRUE;
  3063. }
  3064. switch (HandFlow.FlowReplace & SERIAL_RTS_MASK) {
  3065. case 0:
  3066. lpDCB->fRtsControl = RTS_CONTROL_DISABLE;
  3067. break;
  3068. case SERIAL_RTS_CONTROL:
  3069. lpDCB->fRtsControl = RTS_CONTROL_ENABLE;
  3070. break;
  3071. case SERIAL_RTS_HANDSHAKE:
  3072. lpDCB->fRtsControl = RTS_CONTROL_HANDSHAKE;
  3073. break;
  3074. case SERIAL_TRANSMIT_TOGGLE:
  3075. lpDCB->fRtsControl = RTS_CONTROL_TOGGLE;
  3076. break;
  3077. }
  3078. switch (HandFlow.ControlHandShake & SERIAL_DTR_MASK) {
  3079. case 0:
  3080. lpDCB->fDtrControl = DTR_CONTROL_DISABLE;
  3081. break;
  3082. case SERIAL_DTR_CONTROL:
  3083. lpDCB->fDtrControl = DTR_CONTROL_ENABLE;
  3084. break;
  3085. case SERIAL_DTR_HANDSHAKE:
  3086. lpDCB->fDtrControl = DTR_CONTROL_HANDSHAKE;
  3087. break;
  3088. }
  3089. lpDCB->fDsrSensitivity =
  3090. (HandFlow.ControlHandShake & SERIAL_DSR_SENSITIVITY)?(TRUE):(FALSE);
  3091. lpDCB->XonLim = (WORD)HandFlow.XonLimit;
  3092. lpDCB->XoffLim = (WORD)HandFlow.XoffLimit;
  3093. CloseHandle(SyncEvent);
  3094. return TRUE;
  3095. }
  3096. BOOL
  3097. EscapeCommFunction(
  3098. HANDLE hFile,
  3099. DWORD dwFunc
  3100. )
  3101. /*++
  3102. Routine Description:
  3103. This function directs the communication-device specified by the
  3104. hFile parameter to carry out the extended function specified by
  3105. the dwFunc parameter.
  3106. Arguments:
  3107. hFile - Specifies the communication device to receive the settings.
  3108. The CreateFile function returns this value.
  3109. dwFunc - Specifies the function code of the extended function.
  3110. Return Value:
  3111. The return value is TRUE if the function is successful or FALSE
  3112. if an error occurs.
  3113. --*/
  3114. {
  3115. NTSTATUS Status;
  3116. IO_STATUS_BLOCK Iosb;
  3117. ULONG ControlCode;
  3118. HANDLE Event;
  3119. switch (dwFunc) {
  3120. case SETXOFF: {
  3121. ControlCode = IOCTL_SERIAL_SET_XOFF;
  3122. break;
  3123. }
  3124. case SETXON: {
  3125. ControlCode = IOCTL_SERIAL_SET_XON;
  3126. break;
  3127. }
  3128. case SETRTS: {
  3129. ControlCode = IOCTL_SERIAL_SET_RTS;
  3130. break;
  3131. }
  3132. case CLRRTS: {
  3133. ControlCode = IOCTL_SERIAL_CLR_RTS;
  3134. break;
  3135. }
  3136. case SETDTR: {
  3137. ControlCode = IOCTL_SERIAL_SET_DTR;
  3138. break;
  3139. }
  3140. case CLRDTR: {
  3141. ControlCode = IOCTL_SERIAL_CLR_DTR;
  3142. break;
  3143. }
  3144. case RESETDEV: {
  3145. ControlCode = IOCTL_SERIAL_RESET_DEVICE;
  3146. break;
  3147. }
  3148. case SETBREAK: {
  3149. ControlCode = IOCTL_SERIAL_SET_BREAK_ON;
  3150. break;
  3151. }
  3152. case CLRBREAK: {
  3153. ControlCode = IOCTL_SERIAL_SET_BREAK_OFF;
  3154. break;
  3155. }
  3156. default: {
  3157. SetLastError(ERROR_INVALID_PARAMETER);
  3158. return FALSE;
  3159. }
  3160. }
  3161. if (!(Event = CreateEvent(
  3162. NULL,
  3163. TRUE,
  3164. FALSE,
  3165. NULL
  3166. ))) {
  3167. return FALSE;
  3168. }
  3169. Status = NtDeviceIoControlFile(
  3170. hFile,
  3171. Event,
  3172. NULL,
  3173. NULL,
  3174. &Iosb,
  3175. ControlCode,
  3176. NULL,
  3177. 0,
  3178. NULL,
  3179. 0
  3180. );
  3181. if ( Status == STATUS_PENDING) {
  3182. // Operation must complete before return & IoStatusBlock destroyed
  3183. Status = NtWaitForSingleObject( Event, FALSE, NULL );
  3184. if ( NT_SUCCESS(Status)) {
  3185. Status = Iosb.Status;
  3186. }
  3187. }
  3188. if (NT_ERROR(Status)) {
  3189. CloseHandle(Event);
  3190. BaseSetLastNTError(Status);
  3191. return FALSE;
  3192. }
  3193. CloseHandle(Event);
  3194. return TRUE;
  3195. }
  3196. BOOL
  3197. SetCommState(
  3198. HANDLE hFile,
  3199. LPDCB lpDCB
  3200. )
  3201. /*++
  3202. Routine Description:
  3203. The SetCommState function sets a communication device to the state
  3204. specified in the lpDCB parameter. The device is identified by the
  3205. hFile parameter. This function reinitializes all hardwae and controls
  3206. as specified byt the lpDCB, but does not empty the transmit or
  3207. receive queues.
  3208. Arguments:
  3209. hFile - Specifies the communication device to receive the settings.
  3210. The CreateFile function returns this value.
  3211. lpDCB - Points to a DCB structure that contains the desired
  3212. communications setting for the device.
  3213. Return Value:
  3214. The return value is TRUE if the function is successful or FALSE
  3215. if an error occurs.
  3216. --*/
  3217. {
  3218. SERIAL_BAUD_RATE LocalBaud;
  3219. SERIAL_LINE_CONTROL LineControl;
  3220. SERIAL_CHARS Chars;
  3221. SERIAL_HANDFLOW HandFlow = {0};
  3222. IO_STATUS_BLOCK Iosb;
  3223. NTSTATUS Status;
  3224. //
  3225. // Keep a copy of what the DCB was like before we started
  3226. // changing things. If some error occurs we can use
  3227. // it to restore the old setup.
  3228. //
  3229. DCB OldDcb;
  3230. //
  3231. // Given the possiblity that the app may be doing asynchronous
  3232. // io we need an event to wait on. While it would be very
  3233. // strange to be setting the comm state while IO is active
  3234. // we need to make sure we don't compound the problem by
  3235. // returning before this API's IO is actually finished. This
  3236. // can happen because the file handle is set on the completion
  3237. // of any IO.
  3238. //
  3239. // We need to make sure that any exit to this routine closes this
  3240. // event handle.
  3241. //
  3242. HANDLE SyncEvent;
  3243. if (GetCommState(
  3244. hFile,
  3245. &OldDcb
  3246. )) {
  3247. //
  3248. // Try to set the baud rate. If we fail here, we just return
  3249. // because we never actually got to set anything.
  3250. //
  3251. if (!(SyncEvent = CreateEvent(
  3252. NULL,
  3253. TRUE,
  3254. FALSE,
  3255. NULL
  3256. ))) {
  3257. return FALSE;
  3258. }
  3259. LocalBaud.BaudRate = lpDCB->BaudRate;
  3260. Status = NtDeviceIoControlFile(
  3261. hFile,
  3262. SyncEvent,
  3263. NULL,
  3264. NULL,
  3265. &Iosb,
  3266. IOCTL_SERIAL_SET_BAUD_RATE,
  3267. &LocalBaud,
  3268. sizeof(LocalBaud),
  3269. NULL,
  3270. 0
  3271. );
  3272. if ( Status == STATUS_PENDING) {
  3273. // Operation must complete before return & IoStatusBlock destroyed
  3274. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  3275. if ( NT_SUCCESS(Status)) {
  3276. Status = Iosb.Status;
  3277. }
  3278. }
  3279. if (NT_ERROR(Status)) {
  3280. CloseHandle(SyncEvent);
  3281. BaseSetLastNTError(Status);
  3282. return FALSE;
  3283. }
  3284. LineControl.StopBits = lpDCB->StopBits;
  3285. LineControl.Parity = lpDCB->Parity;
  3286. LineControl.WordLength = lpDCB->ByteSize;
  3287. LocalBaud.BaudRate = lpDCB->BaudRate;
  3288. Chars.XonChar = lpDCB->XonChar;
  3289. Chars.XoffChar = lpDCB->XoffChar;
  3290. Chars.ErrorChar = lpDCB->ErrorChar;
  3291. Chars.BreakChar = lpDCB->ErrorChar;
  3292. Chars.EofChar = lpDCB->EofChar;
  3293. Chars.EventChar = lpDCB->EvtChar;
  3294. HandFlow.FlowReplace &= ~SERIAL_RTS_MASK;
  3295. switch (lpDCB->fRtsControl) {
  3296. case RTS_CONTROL_DISABLE:
  3297. break;
  3298. case RTS_CONTROL_ENABLE:
  3299. HandFlow.FlowReplace |= SERIAL_RTS_CONTROL;
  3300. break;
  3301. case RTS_CONTROL_HANDSHAKE:
  3302. HandFlow.FlowReplace |= SERIAL_RTS_HANDSHAKE;
  3303. break;
  3304. case RTS_CONTROL_TOGGLE:
  3305. HandFlow.FlowReplace |= SERIAL_TRANSMIT_TOGGLE;
  3306. break;
  3307. default:
  3308. SetCommState(
  3309. hFile,
  3310. &OldDcb
  3311. );
  3312. CloseHandle(SyncEvent);
  3313. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  3314. return FALSE;
  3315. }
  3316. HandFlow.ControlHandShake &= ~SERIAL_DTR_MASK;
  3317. switch (lpDCB->fDtrControl) {
  3318. case DTR_CONTROL_DISABLE:
  3319. break;
  3320. case DTR_CONTROL_ENABLE:
  3321. HandFlow.ControlHandShake |= SERIAL_DTR_CONTROL;
  3322. break;
  3323. case DTR_CONTROL_HANDSHAKE:
  3324. HandFlow.ControlHandShake |= SERIAL_DTR_HANDSHAKE;
  3325. break;
  3326. default:
  3327. SetCommState(
  3328. hFile,
  3329. &OldDcb
  3330. );
  3331. CloseHandle(SyncEvent);
  3332. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  3333. return FALSE;
  3334. }
  3335. if (lpDCB->fDsrSensitivity) {
  3336. HandFlow.ControlHandShake |= SERIAL_DSR_SENSITIVITY;
  3337. }
  3338. if (lpDCB->fOutxCtsFlow) {
  3339. HandFlow.ControlHandShake |= SERIAL_CTS_HANDSHAKE;
  3340. }
  3341. if (lpDCB->fOutxDsrFlow) {
  3342. HandFlow.ControlHandShake |= SERIAL_DSR_HANDSHAKE;
  3343. }
  3344. if (lpDCB->fOutX) {
  3345. HandFlow.FlowReplace |= SERIAL_AUTO_TRANSMIT;
  3346. }
  3347. if (lpDCB->fInX) {
  3348. HandFlow.FlowReplace |= SERIAL_AUTO_RECEIVE;
  3349. }
  3350. if (lpDCB->fNull) {
  3351. HandFlow.FlowReplace |= SERIAL_NULL_STRIPPING;
  3352. }
  3353. if (lpDCB->fErrorChar) {
  3354. HandFlow.FlowReplace |= SERIAL_ERROR_CHAR;
  3355. }
  3356. if (lpDCB->fTXContinueOnXoff) {
  3357. HandFlow.FlowReplace |= SERIAL_XOFF_CONTINUE;
  3358. }
  3359. if (lpDCB->fAbortOnError) {
  3360. HandFlow.ControlHandShake |= SERIAL_ERROR_ABORT;
  3361. }
  3362. //
  3363. // For win95 compatiblity, if we are setting with
  3364. // xxx_control_XXXXXXX then set the modem status line
  3365. // to that state.
  3366. //
  3367. if (lpDCB->fRtsControl == RTS_CONTROL_ENABLE) {
  3368. EscapeCommFunction(
  3369. hFile,
  3370. SETRTS
  3371. );
  3372. } else if (lpDCB->fRtsControl == RTS_CONTROL_DISABLE) {
  3373. EscapeCommFunction(
  3374. hFile,
  3375. CLRRTS
  3376. );
  3377. }
  3378. if (lpDCB->fDtrControl == DTR_CONTROL_ENABLE) {
  3379. EscapeCommFunction(
  3380. hFile,
  3381. SETDTR
  3382. );
  3383. } else if (lpDCB->fDtrControl == DTR_CONTROL_DISABLE) {
  3384. EscapeCommFunction(
  3385. hFile,
  3386. CLRDTR
  3387. );
  3388. }
  3389. HandFlow.XonLimit = lpDCB->XonLim;
  3390. HandFlow.XoffLimit = lpDCB->XoffLim;
  3391. Status = NtDeviceIoControlFile(
  3392. hFile,
  3393. SyncEvent,
  3394. NULL,
  3395. NULL,
  3396. &Iosb,
  3397. IOCTL_SERIAL_SET_LINE_CONTROL,
  3398. &LineControl,
  3399. sizeof(LineControl),
  3400. NULL,
  3401. 0
  3402. );
  3403. if ( Status == STATUS_PENDING) {
  3404. // Operation must complete before return & IoStatusBlock destroyed
  3405. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  3406. if ( NT_SUCCESS(Status)) {
  3407. Status = Iosb.Status;
  3408. }
  3409. }
  3410. if (NT_ERROR(Status)) {
  3411. CloseHandle(SyncEvent);
  3412. SetCommState(
  3413. hFile,
  3414. &OldDcb
  3415. );
  3416. BaseSetLastNTError(Status);
  3417. return FALSE;
  3418. }
  3419. Status = NtDeviceIoControlFile(
  3420. hFile,
  3421. SyncEvent,
  3422. NULL,
  3423. NULL,
  3424. &Iosb,
  3425. IOCTL_SERIAL_SET_CHARS,
  3426. &Chars,
  3427. sizeof(Chars),
  3428. NULL,
  3429. 0
  3430. );
  3431. if ( Status == STATUS_PENDING) {
  3432. // Operation must complete before return & IoStatusBlock destroyed
  3433. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  3434. if ( NT_SUCCESS(Status)) {
  3435. Status = Iosb.Status;
  3436. }
  3437. }
  3438. if (NT_ERROR(Status)) {
  3439. CloseHandle(SyncEvent);
  3440. SetCommState(
  3441. hFile,
  3442. &OldDcb
  3443. );
  3444. BaseSetLastNTError(Status);
  3445. return FALSE;
  3446. }
  3447. Status = NtDeviceIoControlFile(
  3448. hFile,
  3449. SyncEvent,
  3450. NULL,
  3451. NULL,
  3452. &Iosb,
  3453. IOCTL_SERIAL_SET_HANDFLOW,
  3454. &HandFlow,
  3455. sizeof(HandFlow),
  3456. NULL,
  3457. 0
  3458. );
  3459. if ( Status == STATUS_PENDING) {
  3460. // Operation must complete before return & IoStatusBlock destroyed
  3461. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  3462. if ( NT_SUCCESS(Status)) {
  3463. Status = Iosb.Status;
  3464. }
  3465. }
  3466. if (NT_ERROR(Status)) {
  3467. CloseHandle(SyncEvent);
  3468. SetCommState(
  3469. hFile,
  3470. &OldDcb
  3471. );
  3472. BaseSetLastNTError(Status);
  3473. return FALSE;
  3474. }
  3475. CloseHandle(SyncEvent);
  3476. return TRUE;
  3477. }
  3478. return FALSE;
  3479. }
  3480. BOOL
  3481. SetCommTimeouts(
  3482. HANDLE hFile,
  3483. LPCOMMTIMEOUTS lpCommTimeouts
  3484. )
  3485. /*++
  3486. Routine Description:
  3487. This function establishes the timeout characteristics for all
  3488. read and write operations on the handle specified by hFile.
  3489. Arguments:
  3490. hFile - Specifies the communication device to receive the settings.
  3491. The CreateFile function returns this value.
  3492. lpCommTimeouts - Points to a structure containing timeout parameters.
  3493. Return Value:
  3494. The return value is TRUE if the function is successful or FALSE
  3495. if an error occurs.
  3496. --*/
  3497. {
  3498. SERIAL_TIMEOUTS To;
  3499. NTSTATUS Status;
  3500. IO_STATUS_BLOCK Iosb;
  3501. HANDLE Event;
  3502. To.ReadIntervalTimeout = lpCommTimeouts->ReadIntervalTimeout;
  3503. To.ReadTotalTimeoutMultiplier = lpCommTimeouts->ReadTotalTimeoutMultiplier;
  3504. To.ReadTotalTimeoutConstant = lpCommTimeouts->ReadTotalTimeoutConstant;
  3505. To.WriteTotalTimeoutMultiplier = lpCommTimeouts->WriteTotalTimeoutMultiplier;
  3506. To.WriteTotalTimeoutConstant = lpCommTimeouts->WriteTotalTimeoutConstant;
  3507. if (!(Event = CreateEvent(
  3508. NULL,
  3509. TRUE,
  3510. FALSE,
  3511. NULL
  3512. ))) {
  3513. return FALSE;
  3514. } else {
  3515. Status = NtDeviceIoControlFile(
  3516. hFile,
  3517. Event,
  3518. NULL,
  3519. NULL,
  3520. &Iosb,
  3521. IOCTL_SERIAL_SET_TIMEOUTS,
  3522. &To,
  3523. sizeof(To),
  3524. NULL,
  3525. 0
  3526. );
  3527. if ( Status == STATUS_PENDING) {
  3528. // Operation must complete before return & IoStatusBlock destroyed
  3529. Status = NtWaitForSingleObject( Event, FALSE, NULL );
  3530. if ( NT_SUCCESS(Status)) {
  3531. Status = Iosb.Status;
  3532. }
  3533. }
  3534. if (NT_ERROR(Status)) {
  3535. CloseHandle(Event);
  3536. BaseSetLastNTError(Status);
  3537. return FALSE;
  3538. }
  3539. CloseHandle(Event);
  3540. return TRUE;
  3541. }
  3542. }
  3543. BOOL
  3544. APIENTRY
  3545. InitializeSecurityDescriptor (
  3546. PSECURITY_DESCRIPTOR pSecurityDescriptor,
  3547. DWORD dwRevision
  3548. )
  3549. {
  3550. NTSTATUS Status;
  3551. Status = RtlCreateSecurityDescriptor (
  3552. pSecurityDescriptor,
  3553. dwRevision
  3554. );
  3555. if ( !NT_SUCCESS(Status) ) {
  3556. BaseSetLastNTError(Status);
  3557. return FALSE;
  3558. }
  3559. return TRUE;
  3560. }
  3561. BOOL
  3562. APIENTRY
  3563. SetSecurityDescriptorDacl (
  3564. PSECURITY_DESCRIPTOR pSecurityDescriptor,
  3565. BOOL bDaclPresent,
  3566. PACL pDacl OPTIONAL,
  3567. BOOL bDaclDefaulted OPTIONAL
  3568. )
  3569. {
  3570. NTSTATUS Status;
  3571. Status = RtlSetDaclSecurityDescriptor (
  3572. pSecurityDescriptor,
  3573. (BOOLEAN)bDaclPresent,
  3574. pDacl,
  3575. (BOOLEAN)bDaclDefaulted
  3576. );
  3577. if ( !NT_SUCCESS(Status) ) {
  3578. BaseSetLastNTError(Status);
  3579. return FALSE;
  3580. }
  3581. return TRUE;
  3582. }
  3583. BOOL
  3584. APIENTRY
  3585. InitializeAcl (
  3586. PACL pAcl,
  3587. DWORD nAclLength,
  3588. DWORD dwAclRevision
  3589. )
  3590. /*++
  3591. Routine Description:
  3592. InitializeAcl creates a new ACL in the caller supplied memory
  3593. buffer. The ACL contains zero ACEs; therefore, it is an empty ACL
  3594. as opposed to a nonexistent ACL. That is, if the ACL is now set
  3595. to an object it will implicitly deny access to everyone.
  3596. Arguments:
  3597. pAcl - Supplies the buffer containing the ACL being initialized
  3598. nAclLength - Supplies the length of the ace buffer in bytes
  3599. dwAclRevision - Supplies the revision for this Acl
  3600. Return Value:
  3601. Returns TRUE for success, FALSE for failure. Extended error status
  3602. is available using GetLastError.
  3603. --*/
  3604. {
  3605. NTSTATUS Status;
  3606. Status = RtlCreateAcl (
  3607. pAcl,
  3608. nAclLength,
  3609. dwAclRevision
  3610. );
  3611. if ( !NT_SUCCESS(Status) ) {
  3612. BaseSetLastNTError(Status);
  3613. return FALSE;
  3614. }
  3615. return TRUE;
  3616. }
  3617. BOOL
  3618. APIENTRY
  3619. AddAccessAllowedAce (
  3620. PACL pAcl,
  3621. DWORD dwAceRevision,
  3622. DWORD AccessMask,
  3623. PSID pSid
  3624. )
  3625. /*++
  3626. Routine Description:
  3627. This routine adds an ACCESS_ALLOWED ACE to an ACL. This is
  3628. expected to be a common form of ACL modification.
  3629. A very bland ACE header is placed in the ACE. It provides no
  3630. inheritance and no ACE flags.
  3631. Arguments:
  3632. PAcl - Supplies the Acl being modified
  3633. dwAceRevision - Supplies the Acl/Ace revision of the ACE being added
  3634. AccessMask - The mask of accesses to be granted to the specified SID.
  3635. pSid - Pointer to the SID being granted access.
  3636. Return Value:
  3637. Returns TRUE for success, FALSE for failure. Extended error status
  3638. is available using GetLastError.
  3639. --*/
  3640. {
  3641. NTSTATUS Status;
  3642. Status = RtlAddAccessAllowedAce (
  3643. pAcl,
  3644. dwAceRevision,
  3645. AccessMask,
  3646. pSid
  3647. );
  3648. if ( !NT_SUCCESS(Status) ) {
  3649. BaseSetLastNTError(Status);
  3650. return FALSE;
  3651. }
  3652. return TRUE;
  3653. }
  3654. BOOL
  3655. APIENTRY
  3656. AddAccessDeniedAce (
  3657. PACL pAcl,
  3658. DWORD dwAceRevision,
  3659. DWORD AccessMask,
  3660. PSID pSid
  3661. )
  3662. /*++
  3663. Routine Description:
  3664. This routine adds an ACCESS_DENIED ACE to an ACL. This is
  3665. expected to be a common form of ACL modification.
  3666. A very bland ACE header is placed in the ACE. It provides no
  3667. inheritance and no ACE flags.
  3668. Arguments:
  3669. pAcl - Supplies the Acl being modified
  3670. dwAceRevision - Supplies the Acl/Ace revision of the ACE being added
  3671. AccessMask - The mask of accesses to be denied to the specified SID.
  3672. pSid - Pointer to the SID being denied access.
  3673. Return Value:
  3674. Returns TRUE for success, FALSE for failure. Extended error status
  3675. is available using GetLastError.
  3676. --*/
  3677. {
  3678. NTSTATUS Status;
  3679. Status = RtlAddAccessDeniedAce (
  3680. pAcl,
  3681. dwAceRevision,
  3682. AccessMask,
  3683. pSid
  3684. );
  3685. if ( !NT_SUCCESS(Status) ) {
  3686. BaseSetLastNTError(Status);
  3687. return FALSE;
  3688. }
  3689. return TRUE;
  3690. }
  3691. PVOID
  3692. APIENTRY
  3693. FreeSid(
  3694. PSID pSid
  3695. )
  3696. /*++
  3697. Routine Description:
  3698. This function is used to free a SID previously allocated using
  3699. AllocateAndInitializeSid().
  3700. Arguments:
  3701. Sid - Pointer to the SID to free.
  3702. Return Value:
  3703. None.
  3704. --*/
  3705. {
  3706. return(RtlFreeSid( pSid ));
  3707. }
  3708. DWORD
  3709. APIENTRY
  3710. GetLengthSid (
  3711. PSID pSid
  3712. )
  3713. /*++
  3714. Routine Description:
  3715. This routine returns the length, in bytes, of a structurally valid SID.
  3716. Arguments:
  3717. pSid - Points to the SID whose length is to be returned. The
  3718. SID's structure is assumed to be valid.
  3719. Return Value:
  3720. DWORD - The length, in bytes, of the SID.
  3721. --*/
  3722. {
  3723. SetLastError(0);
  3724. return RtlLengthSid (
  3725. pSid
  3726. );
  3727. }
  3728. BOOL
  3729. APIENTRY
  3730. AllocateAndInitializeSid (
  3731. PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
  3732. BYTE nSubAuthorityCount,
  3733. DWORD nSubAuthority0,
  3734. DWORD nSubAuthority1,
  3735. DWORD nSubAuthority2,
  3736. DWORD nSubAuthority3,
  3737. DWORD nSubAuthority4,
  3738. DWORD nSubAuthority5,
  3739. DWORD nSubAuthority6,
  3740. DWORD nSubAuthority7,
  3741. PSID *pSid
  3742. )
  3743. /*++
  3744. Routine Description:
  3745. This function allocates and initializes a sid with the specified
  3746. number of sub-authorities (up to 8). A sid allocated with this
  3747. routine must be freed using FreeSid().
  3748. Arguments:
  3749. pIdentifierAuthority - Pointer to the Identifier Authority value to
  3750. set in the SID.
  3751. nSubAuthorityCount - The number of sub-authorities to place in the SID.
  3752. This also identifies how many of the SubAuthorityN parameters
  3753. have meaningful values. This must contain a value from 0 through
  3754. 8.
  3755. nSubAuthority0-7 - Provides the corresponding sub-authority value to
  3756. place in the SID. For example, a SubAuthorityCount value of 3
  3757. indicates that SubAuthority0, SubAuthority1, and SubAuthority0
  3758. have meaningful values and the rest are to be ignored.
  3759. Sid - Receives a pointer to the allocated and initialized SID data
  3760. structure.
  3761. Return Value:
  3762. ERROR_NO_MEMORY - The attempt to allocate memory for the SID
  3763. failed.
  3764. ERROR_INVALID_SID - The number of sub-authorities specified did
  3765. not fall in the valid range for this api (0 through 8).
  3766. --*/
  3767. {
  3768. NTSTATUS Status;
  3769. Status = RtlAllocateAndInitializeSid (
  3770. pIdentifierAuthority,
  3771. (UCHAR)nSubAuthorityCount,
  3772. (ULONG)nSubAuthority0,
  3773. (ULONG)nSubAuthority1,
  3774. (ULONG)nSubAuthority2,
  3775. (ULONG)nSubAuthority3,
  3776. (ULONG)nSubAuthority4,
  3777. (ULONG)nSubAuthority5,
  3778. (ULONG)nSubAuthority6,
  3779. (ULONG)nSubAuthority7,
  3780. pSid
  3781. );
  3782. if ( !NT_SUCCESS( Status )) {
  3783. BaseSetLastNTError( Status );
  3784. return( FALSE );
  3785. }
  3786. return( TRUE );
  3787. }
  3788. ULONG
  3789. APIENTRY
  3790. GetTickCount(void)
  3791. {
  3792. return NtGetTickCount();
  3793. }
  3794. LPSTR
  3795. WINAPI
  3796. GetCommandLineA(
  3797. VOID
  3798. )
  3799. {
  3800. // Purely to allow linkage, not expected to be used.
  3801. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  3802. return NULL;
  3803. }
  3804. LPWSTR
  3805. WINAPI
  3806. GetCommandLineW(
  3807. VOID
  3808. )
  3809. {
  3810. return NtCurrentPeb()->ProcessParameters->CommandLine.Buffer;
  3811. }
  3812. #endif // #ifdef NT_NATIVE