Source code of Windows XP (NT5)
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.

4326 lines
111 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Support routines for NT-native binaries.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000-2001.
  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, [esp+4] ; (ecx) = Target
  84. mov edx, [esp+8] ; (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;
  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;
  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;
  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;
  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. RTL_RELATIVE_NAME RelativeName;
  645. PVOID FreeBuffer;
  646. ULONG CreateDisposition;
  647. ULONG CreateFlags = 0;
  648. FILE_ALLOCATION_INFORMATION AllocationInfo;
  649. PUNICODE_STRING lpConsoleName;
  650. BOOL bInheritHandle;
  651. BOOL EndsInSlash;
  652. DWORD SQOSFlags;
  653. BOOLEAN ContextTrackingMode = FALSE;
  654. BOOLEAN EffectiveOnly = FALSE;
  655. SECURITY_IMPERSONATION_LEVEL ImpersonationLevel = SecurityAnonymous;
  656. SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
  657. if (ARGUMENT_PRESENT(hTemplateFile))
  658. {
  659. return INVALID_HANDLE_VALUE;
  660. }
  661. switch ( dwCreationDisposition )
  662. {
  663. case CREATE_NEW :
  664. CreateDisposition = FILE_CREATE;
  665. break;
  666. case CREATE_ALWAYS :
  667. CreateDisposition = FILE_OVERWRITE_IF;
  668. break;
  669. case OPEN_EXISTING :
  670. CreateDisposition = FILE_OPEN;
  671. break;
  672. case OPEN_ALWAYS :
  673. CreateDisposition = FILE_OPEN_IF;
  674. break;
  675. case TRUNCATE_EXISTING :
  676. CreateDisposition = FILE_OPEN;
  677. if ( !(dwDesiredAccess & GENERIC_WRITE) )
  678. {
  679. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  680. return INVALID_HANDLE_VALUE;
  681. }
  682. break;
  683. default :
  684. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  685. return INVALID_HANDLE_VALUE;
  686. }
  687. RtlInitUnicodeString(&FileName,lpFileName);
  688. if (TranslatePath)
  689. {
  690. TranslationStatus = RtlDosPathNameToNtPathName_U(lpFileName,
  691. &FileName,
  692. NULL,
  693. &RelativeName
  694. );
  695. if ( !TranslationStatus )
  696. {
  697. SetLastError(ERROR_PATH_NOT_FOUND);
  698. return INVALID_HANDLE_VALUE;
  699. }
  700. FreeBuffer = FileName.Buffer;
  701. if ( RelativeName.RelativeName.Length )
  702. {
  703. FileName = *(PUNICODE_STRING)&RelativeName.RelativeName;
  704. }
  705. else
  706. {
  707. RelativeName.ContainingDirectory = NULL;
  708. }
  709. }
  710. else
  711. {
  712. FreeBuffer = NULL;
  713. RelativeName.ContainingDirectory = NULL;
  714. }
  715. InitializeObjectAttributes(&Obja,
  716. &FileName,
  717. dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS ? 0 : OBJ_CASE_INSENSITIVE,
  718. RelativeName.ContainingDirectory,
  719. NULL
  720. );
  721. SQOSFlags = dwFlagsAndAttributes & SECURITY_VALID_SQOS_FLAGS;
  722. if ( SQOSFlags & SECURITY_SQOS_PRESENT )
  723. {
  724. SQOSFlags &= ~SECURITY_SQOS_PRESENT;
  725. if (SQOSFlags & SECURITY_CONTEXT_TRACKING)
  726. {
  727. SecurityQualityOfService.ContextTrackingMode = (SECURITY_CONTEXT_TRACKING_MODE) TRUE;
  728. SQOSFlags &= ~SECURITY_CONTEXT_TRACKING;
  729. }
  730. else
  731. {
  732. SecurityQualityOfService.ContextTrackingMode = (SECURITY_CONTEXT_TRACKING_MODE) FALSE;
  733. }
  734. if (SQOSFlags & SECURITY_EFFECTIVE_ONLY)
  735. {
  736. SecurityQualityOfService.EffectiveOnly = TRUE;
  737. SQOSFlags &= ~SECURITY_EFFECTIVE_ONLY;
  738. }
  739. else
  740. {
  741. SecurityQualityOfService.EffectiveOnly = FALSE;
  742. }
  743. SecurityQualityOfService.ImpersonationLevel = (SECURITY_IMPERSONATION_LEVEL)(SQOSFlags >> 16);
  744. }
  745. else
  746. {
  747. SecurityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  748. SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation;
  749. SecurityQualityOfService.EffectiveOnly = TRUE;
  750. }
  751. SecurityQualityOfService.Length = sizeof( SECURITY_QUALITY_OF_SERVICE );
  752. Obja.SecurityQualityOfService = &SecurityQualityOfService;
  753. if ( ARGUMENT_PRESENT(lpSecurityAttributes) )
  754. {
  755. Obja.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
  756. if ( lpSecurityAttributes->bInheritHandle )
  757. {
  758. Obja.Attributes |= OBJ_INHERIT;
  759. }
  760. }
  761. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING ? FILE_NO_INTERMEDIATE_BUFFERING : 0 );
  762. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH ? FILE_WRITE_THROUGH : 0 );
  763. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED ? 0 : FILE_SYNCHRONOUS_IO_NONALERT );
  764. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN ? FILE_SEQUENTIAL_ONLY : 0 );
  765. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS ? FILE_RANDOM_ACCESS : 0 );
  766. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS ? FILE_OPEN_FOR_BACKUP_INTENT : 0 );
  767. if ( dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE )
  768. {
  769. CreateFlags |= FILE_DELETE_ON_CLOSE;
  770. dwDesiredAccess |= DELETE;
  771. }
  772. if ( dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT )
  773. {
  774. CreateFlags |= FILE_OPEN_REPARSE_POINT;
  775. }
  776. if ( dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL )
  777. {
  778. CreateFlags |= FILE_OPEN_NO_RECALL;
  779. }
  780. //
  781. // Backup semantics allow directories to be opened
  782. //
  783. if ( !(dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS) )
  784. {
  785. CreateFlags |= FILE_NON_DIRECTORY_FILE;
  786. }
  787. else
  788. {
  789. //
  790. // Backup intent was specified... Now look to see if we are to allow
  791. // directory creation
  792. //
  793. if ( (dwFlagsAndAttributes & FILE_ATTRIBUTE_DIRECTORY ) &&
  794. (dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS ) &&
  795. (CreateDisposition == FILE_CREATE) )
  796. {
  797. CreateFlags |= FILE_DIRECTORY_FILE;
  798. }
  799. }
  800. Status = NtCreateFile(&Handle,
  801. (ACCESS_MASK)dwDesiredAccess | SYNCHRONIZE | FILE_READ_ATTRIBUTES,
  802. &Obja,
  803. &IoStatusBlock,
  804. NULL,
  805. dwFlagsAndAttributes & (FILE_ATTRIBUTE_VALID_FLAGS & ~FILE_ATTRIBUTE_DIRECTORY),
  806. dwShareMode,
  807. CreateDisposition,
  808. CreateFlags,
  809. NULL,
  810. 0
  811. );
  812. if (FreeBuffer != NULL)
  813. {
  814. RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
  815. }
  816. if ( !NT_SUCCESS(Status) )
  817. {
  818. BaseSetLastNTError(Status);
  819. if ( Status == STATUS_OBJECT_NAME_COLLISION )
  820. {
  821. SetLastError(ERROR_FILE_EXISTS);
  822. }
  823. else if ( Status == STATUS_FILE_IS_A_DIRECTORY )
  824. {
  825. SetLastError(ERROR_ACCESS_DENIED);
  826. }
  827. return INVALID_HANDLE_VALUE;
  828. }
  829. //
  830. // if NT returns supersede/overwritten, it means that a create_always, openalways
  831. // found an existing copy of the file. In this case ERROR_ALREADY_EXISTS is returned
  832. //
  833. if ( (dwCreationDisposition == CREATE_ALWAYS && IoStatusBlock.Information ==
  834. FILE_OVERWRITTEN) ||
  835. (dwCreationDisposition == OPEN_ALWAYS && IoStatusBlock.Information == FILE_OPENED) )
  836. {
  837. SetLastError(ERROR_ALREADY_EXISTS);
  838. }
  839. else
  840. {
  841. SetLastError(0);
  842. }
  843. //
  844. // Truncate the file if required
  845. //
  846. if ( dwCreationDisposition == TRUNCATE_EXISTING)
  847. {
  848. AllocationInfo.AllocationSize.QuadPart = 0;
  849. Status = NtSetInformationFile(Handle,
  850. &IoStatusBlock,
  851. &AllocationInfo,
  852. sizeof(AllocationInfo),
  853. FileAllocationInformation
  854. );
  855. if ( !NT_SUCCESS(Status) )
  856. {
  857. BaseSetLastNTError(Status);
  858. NtClose(Handle);
  859. Handle = INVALID_HANDLE_VALUE;
  860. }
  861. }
  862. return Handle;
  863. }
  864. HANDLE
  865. WINAPI
  866. NtNativeCreateFileA(
  867. LPCSTR lpFileName,
  868. DWORD dwDesiredAccess,
  869. DWORD dwShareMode,
  870. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  871. DWORD dwCreationDisposition,
  872. DWORD dwFlagsAndAttributes,
  873. HANDLE hTemplateFile,
  874. BOOL TranslatePath
  875. )
  876. {
  877. NTSTATUS Status;
  878. ANSI_STRING AnsiFile;
  879. UNICODE_STRING WideFile;
  880. RtlInitAnsiString(&AnsiFile, lpFileName);
  881. Status = RtlAnsiStringToUnicodeString(&WideFile, &AnsiFile, TRUE);
  882. if (!NT_SUCCESS(Status))
  883. {
  884. BaseSetLastNTError(Status);
  885. return FALSE;
  886. }
  887. HANDLE File;
  888. File = NtNativeCreateFileW(WideFile.Buffer, dwDesiredAccess, dwShareMode,
  889. lpSecurityAttributes, dwCreationDisposition,
  890. dwFlagsAndAttributes, hTemplateFile,
  891. TranslatePath);
  892. RtlFreeUnicodeString(&WideFile);
  893. return File;
  894. }
  895. HANDLE
  896. WINAPI
  897. CreateFileA(
  898. LPCSTR lpFileName,
  899. DWORD dwDesiredAccess,
  900. DWORD dwShareMode,
  901. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  902. DWORD dwCreationDisposition,
  903. DWORD dwFlagsAndAttributes,
  904. HANDLE hTemplateFile
  905. )
  906. {
  907. return NtNativeCreateFileA(lpFileName, dwDesiredAccess, dwShareMode,
  908. lpSecurityAttributes, dwCreationDisposition,
  909. dwFlagsAndAttributes, hTemplateFile,
  910. TRUE);
  911. }
  912. BOOL
  913. WINAPI
  914. DeviceIoControl(
  915. HANDLE hDevice,
  916. DWORD dwIoControlCode,
  917. LPVOID lpInBuffer,
  918. DWORD nInBufferSize,
  919. LPVOID lpOutBuffer,
  920. DWORD nOutBufferSize,
  921. LPDWORD lpBytesReturned,
  922. LPOVERLAPPED lpOverlapped
  923. )
  924. {
  925. if ((dwIoControlCode >> 16) == FILE_DEVICE_FILE_SYSTEM ||
  926. lpOverlapped != NULL)
  927. {
  928. return FALSE;
  929. }
  930. IO_STATUS_BLOCK Iosb;
  931. NTSTATUS Status;
  932. Status = NtDeviceIoControlFile(hDevice,
  933. NULL,
  934. NULL, // APC routine
  935. NULL, // APC Context
  936. &Iosb,
  937. dwIoControlCode, // IoControlCode
  938. lpInBuffer, // Buffer for data to the FS
  939. nInBufferSize,
  940. lpOutBuffer, // OutputBuffer for data from the FS
  941. nOutBufferSize // OutputBuffer Length
  942. );
  943. if ( Status == STATUS_PENDING)
  944. {
  945. // Operation must complete before return & Iosb destroyed
  946. Status = NtWaitForSingleObject( hDevice, FALSE, NULL );
  947. if ( NT_SUCCESS(Status))
  948. {
  949. Status = Iosb.Status;
  950. }
  951. }
  952. if ( NT_SUCCESS(Status) )
  953. {
  954. *lpBytesReturned = (DWORD)Iosb.Information;
  955. return TRUE;
  956. }
  957. else
  958. {
  959. // handle warning value STATUS_BUFFER_OVERFLOW somewhat correctly
  960. if ( !NT_ERROR(Status) )
  961. {
  962. *lpBytesReturned = (DWORD)Iosb.Information;
  963. }
  964. BaseSetLastNTError(Status);
  965. return FALSE;
  966. }
  967. }
  968. BOOL
  969. WINAPI
  970. ReadFile(
  971. HANDLE hFile,
  972. LPVOID lpBuffer,
  973. DWORD nNumberOfBytesToRead,
  974. LPDWORD lpNumberOfBytesRead,
  975. LPOVERLAPPED lpOverlapped
  976. )
  977. {
  978. NTSTATUS Status;
  979. IO_STATUS_BLOCK IoStatusBlock;
  980. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) )
  981. {
  982. *lpNumberOfBytesRead = 0;
  983. }
  984. if ( ARGUMENT_PRESENT( lpOverlapped ) )
  985. {
  986. LARGE_INTEGER Li;
  987. lpOverlapped->Internal = (DWORD)STATUS_PENDING;
  988. Li.LowPart = lpOverlapped->Offset;
  989. Li.HighPart = lpOverlapped->OffsetHigh;
  990. Status = NtReadFile(
  991. hFile,
  992. lpOverlapped->hEvent,
  993. NULL,
  994. (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped,
  995. (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  996. lpBuffer,
  997. nNumberOfBytesToRead,
  998. &Li,
  999. NULL
  1000. );
  1001. if ( NT_SUCCESS(Status) && Status != STATUS_PENDING)
  1002. {
  1003. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) )
  1004. {
  1005. __try
  1006. {
  1007. *lpNumberOfBytesRead = (DWORD)lpOverlapped->InternalHigh;
  1008. }
  1009. __except(EXCEPTION_EXECUTE_HANDLER)
  1010. {
  1011. *lpNumberOfBytesRead = 0;
  1012. }
  1013. }
  1014. return TRUE;
  1015. }
  1016. else if (Status == STATUS_END_OF_FILE)
  1017. {
  1018. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) )
  1019. {
  1020. *lpNumberOfBytesRead = 0;
  1021. }
  1022. BaseSetLastNTError(Status);
  1023. return FALSE;
  1024. }
  1025. else
  1026. {
  1027. BaseSetLastNTError(Status);
  1028. return FALSE;
  1029. }
  1030. }
  1031. else
  1032. {
  1033. Status = NtReadFile(hFile,
  1034. NULL,
  1035. NULL,
  1036. NULL,
  1037. &IoStatusBlock,
  1038. lpBuffer,
  1039. nNumberOfBytesToRead,
  1040. NULL,
  1041. NULL
  1042. );
  1043. if ( Status == STATUS_PENDING)
  1044. {
  1045. // Operation must complete before return & IoStatusBlock destroyed
  1046. Status = NtWaitForSingleObject( hFile, FALSE, NULL );
  1047. if ( NT_SUCCESS(Status))
  1048. {
  1049. Status = IoStatusBlock.Status;
  1050. }
  1051. }
  1052. if ( NT_SUCCESS(Status) )
  1053. {
  1054. *lpNumberOfBytesRead = (DWORD)IoStatusBlock.Information;
  1055. return TRUE;
  1056. }
  1057. else
  1058. {
  1059. if (Status == STATUS_END_OF_FILE)
  1060. {
  1061. *lpNumberOfBytesRead = 0;
  1062. return TRUE;
  1063. }
  1064. else
  1065. {
  1066. if ( NT_WARNING(Status) )
  1067. {
  1068. *lpNumberOfBytesRead = (DWORD)IoStatusBlock.Information;
  1069. }
  1070. BaseSetLastNTError(Status);
  1071. return FALSE;
  1072. }
  1073. }
  1074. }
  1075. }
  1076. BOOL
  1077. WINAPI
  1078. WriteFile(
  1079. HANDLE hFile,
  1080. LPCVOID lpBuffer,
  1081. DWORD nNumberOfBytesToWrite,
  1082. LPDWORD lpNumberOfBytesWritten,
  1083. LPOVERLAPPED lpOverlapped
  1084. )
  1085. {
  1086. NTSTATUS Status;
  1087. IO_STATUS_BLOCK IoStatusBlock;
  1088. if ( ARGUMENT_PRESENT(lpNumberOfBytesWritten) )
  1089. {
  1090. *lpNumberOfBytesWritten = 0;
  1091. }
  1092. if ( ARGUMENT_PRESENT( lpOverlapped ) )
  1093. {
  1094. LARGE_INTEGER Li;
  1095. lpOverlapped->Internal = (DWORD)STATUS_PENDING;
  1096. Li.LowPart = lpOverlapped->Offset;
  1097. Li.HighPart = lpOverlapped->OffsetHigh;
  1098. Status = NtWriteFile(
  1099. hFile,
  1100. lpOverlapped->hEvent,
  1101. NULL,
  1102. (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped,
  1103. (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  1104. (PVOID)lpBuffer,
  1105. nNumberOfBytesToWrite,
  1106. &Li,
  1107. NULL
  1108. );
  1109. if ( !NT_ERROR(Status) && Status != STATUS_PENDING)
  1110. {
  1111. if ( ARGUMENT_PRESENT(lpNumberOfBytesWritten) )
  1112. {
  1113. __try
  1114. {
  1115. *lpNumberOfBytesWritten = (DWORD)lpOverlapped->InternalHigh;
  1116. }
  1117. __except(EXCEPTION_EXECUTE_HANDLER)
  1118. {
  1119. *lpNumberOfBytesWritten = 0;
  1120. }
  1121. }
  1122. return TRUE;
  1123. }
  1124. else
  1125. {
  1126. BaseSetLastNTError(Status);
  1127. return FALSE;
  1128. }
  1129. }
  1130. else
  1131. {
  1132. Status = NtWriteFile(hFile,
  1133. NULL,
  1134. NULL,
  1135. NULL,
  1136. &IoStatusBlock,
  1137. (PVOID)lpBuffer,
  1138. nNumberOfBytesToWrite,
  1139. NULL,
  1140. NULL
  1141. );
  1142. if ( Status == STATUS_PENDING)
  1143. {
  1144. // Operation must complete before return & IoStatusBlock destroyed
  1145. Status = NtWaitForSingleObject( hFile, FALSE, NULL );
  1146. if ( NT_SUCCESS(Status))
  1147. {
  1148. Status = IoStatusBlock.Status;
  1149. }
  1150. }
  1151. if ( NT_SUCCESS(Status))
  1152. {
  1153. *lpNumberOfBytesWritten = (DWORD)IoStatusBlock.Information;
  1154. return TRUE;
  1155. }
  1156. else
  1157. {
  1158. if ( NT_WARNING(Status) )
  1159. {
  1160. *lpNumberOfBytesWritten = (DWORD)IoStatusBlock.Information;
  1161. }
  1162. BaseSetLastNTError(Status);
  1163. return FALSE;
  1164. }
  1165. }
  1166. }
  1167. SIZE_T
  1168. WINAPI
  1169. VirtualQueryEx(
  1170. HANDLE hProcess,
  1171. LPCVOID lpAddress,
  1172. PMEMORY_BASIC_INFORMATION lpBuffer,
  1173. SIZE_T dwLength
  1174. )
  1175. {
  1176. NTSTATUS Status;
  1177. SIZE_T ReturnLength;
  1178. Status = NtQueryVirtualMemory( hProcess,
  1179. (LPVOID)lpAddress,
  1180. MemoryBasicInformation,
  1181. (PMEMORY_BASIC_INFORMATION)lpBuffer,
  1182. dwLength,
  1183. &ReturnLength
  1184. );
  1185. if (NT_SUCCESS( Status ))
  1186. {
  1187. return( ReturnLength );
  1188. }
  1189. else
  1190. {
  1191. BaseSetLastNTError( Status );
  1192. return( 0 );
  1193. }
  1194. }
  1195. BOOL
  1196. WINAPI
  1197. VirtualProtectEx(
  1198. HANDLE hProcess,
  1199. PVOID lpAddress,
  1200. SIZE_T dwSize,
  1201. DWORD flNewProtect,
  1202. PDWORD lpflOldProtect
  1203. )
  1204. {
  1205. NTSTATUS Status;
  1206. Status = NtProtectVirtualMemory( hProcess,
  1207. &lpAddress,
  1208. &dwSize,
  1209. flNewProtect,
  1210. lpflOldProtect
  1211. );
  1212. if (NT_SUCCESS( Status )) {
  1213. return( TRUE );
  1214. }
  1215. else {
  1216. if (Status == STATUS_INVALID_PAGE_PROTECTION) {
  1217. if (hProcess == NtCurrentProcess()) {
  1218. //
  1219. // Unlock any pages that were locked with MmSecureVirtualMemory.
  1220. // This is useful for SANs.
  1221. //
  1222. if (RtlFlushSecureMemoryCache(lpAddress, dwSize)) {
  1223. Status = NtProtectVirtualMemory( hProcess,
  1224. &lpAddress,
  1225. &dwSize,
  1226. flNewProtect,
  1227. lpflOldProtect
  1228. );
  1229. if (NT_SUCCESS( Status )) {
  1230. return( TRUE );
  1231. }
  1232. }
  1233. }
  1234. }
  1235. BaseSetLastNTError( Status );
  1236. return( FALSE );
  1237. }
  1238. }
  1239. PVOID
  1240. WINAPI
  1241. VirtualAllocEx(
  1242. HANDLE hProcess,
  1243. PVOID lpAddress,
  1244. SIZE_T dwSize,
  1245. DWORD flAllocationType,
  1246. DWORD flProtect
  1247. )
  1248. {
  1249. NTSTATUS Status;
  1250. __try {
  1251. Status = NtAllocateVirtualMemory( hProcess,
  1252. &lpAddress,
  1253. 0,
  1254. &dwSize,
  1255. flAllocationType,
  1256. flProtect
  1257. );
  1258. }
  1259. __except( EXCEPTION_EXECUTE_HANDLER ) {
  1260. Status = GetExceptionCode();
  1261. }
  1262. if (NT_SUCCESS( Status )) {
  1263. return( lpAddress );
  1264. }
  1265. else {
  1266. BaseSetLastNTError( Status );
  1267. return( NULL );
  1268. }
  1269. }
  1270. BOOL
  1271. WINAPI
  1272. VirtualFreeEx(
  1273. HANDLE hProcess,
  1274. LPVOID lpAddress,
  1275. SIZE_T dwSize,
  1276. DWORD dwFreeType
  1277. )
  1278. {
  1279. NTSTATUS Status;
  1280. if ( (dwFreeType & MEM_RELEASE ) && dwSize != 0 ) {
  1281. BaseSetLastNTError( STATUS_INVALID_PARAMETER );
  1282. return FALSE;
  1283. }
  1284. Status = NtFreeVirtualMemory( hProcess,
  1285. &lpAddress,
  1286. &dwSize,
  1287. dwFreeType
  1288. );
  1289. if (NT_SUCCESS( Status )) {
  1290. return( TRUE );
  1291. }
  1292. else {
  1293. if (Status == STATUS_INVALID_PAGE_PROTECTION) {
  1294. if (hProcess == NtCurrentProcess()) {
  1295. //
  1296. // Unlock any pages that were locked with MmSecureVirtualMemory.
  1297. // This is useful for SANs.
  1298. //
  1299. if (RtlFlushSecureMemoryCache(lpAddress, dwSize)) {
  1300. Status = NtFreeVirtualMemory( hProcess,
  1301. &lpAddress,
  1302. &dwSize,
  1303. dwFreeType
  1304. );
  1305. if (NT_SUCCESS( Status )) {
  1306. return( TRUE );
  1307. }
  1308. }
  1309. }
  1310. }
  1311. BaseSetLastNTError( Status );
  1312. return( FALSE );
  1313. }
  1314. }
  1315. HANDLE
  1316. APIENTRY
  1317. CreateThread(
  1318. LPSECURITY_ATTRIBUTES lpThreadAttributes,
  1319. SIZE_T dwStackSize,
  1320. LPTHREAD_START_ROUTINE lpStartAddress,
  1321. LPVOID lpParameter,
  1322. DWORD dwCreationFlags,
  1323. LPDWORD lpThreadId
  1324. )
  1325. {
  1326. return CreateRemoteThread( NtCurrentProcess(),
  1327. lpThreadAttributes,
  1328. dwStackSize,
  1329. lpStartAddress,
  1330. lpParameter,
  1331. dwCreationFlags,
  1332. lpThreadId
  1333. );
  1334. }
  1335. HANDLE
  1336. APIENTRY
  1337. CreateRemoteThread(
  1338. HANDLE hProcess,
  1339. LPSECURITY_ATTRIBUTES lpThreadAttributes,
  1340. SIZE_T dwStackSize,
  1341. LPTHREAD_START_ROUTINE lpStartAddress,
  1342. LPVOID lpParameter,
  1343. DWORD dwCreationFlags,
  1344. LPDWORD lpThreadId
  1345. )
  1346. {
  1347. NTSTATUS Status;
  1348. HANDLE Handle;
  1349. CLIENT_ID ClientId;
  1350. Handle = NULL;
  1351. //
  1352. // Allocate a stack for this thread in the address space of the target
  1353. // process.
  1354. //
  1355. if ((dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION) ||
  1356. dwStackSize != 0 || lpThreadAttributes != NULL)
  1357. {
  1358. return NULL;
  1359. }
  1360. Status = RtlCreateUserThread (hProcess,
  1361. NULL,
  1362. (dwCreationFlags & CREATE_SUSPENDED) ?
  1363. TRUE : FALSE,
  1364. 0,
  1365. 0,
  1366. 0,
  1367. (PUSER_THREAD_START_ROUTINE)lpStartAddress,
  1368. lpParameter,
  1369. &Handle,
  1370. &ClientId);
  1371. if ( ARGUMENT_PRESENT(lpThreadId) )
  1372. {
  1373. *lpThreadId = HandleToUlong(ClientId.UniqueThread);
  1374. }
  1375. return Handle;
  1376. }
  1377. #define DOS_LOCAL_PIPE_PREFIX L"\\\\.\\pipe\\"
  1378. #define DOS_LOCAL_PIPE L"\\DosDevices\\pipe\\"
  1379. #define DOS_REMOTE_PIPE L"\\DosDevices\\UNC\\"
  1380. #define INVALID_PIPE_MODE_BITS ~(PIPE_READMODE_BYTE \
  1381. | PIPE_READMODE_MESSAGE \
  1382. | PIPE_WAIT \
  1383. | PIPE_NOWAIT)
  1384. HANDLE
  1385. APIENTRY
  1386. NtNativeCreateNamedPipeW(
  1387. LPCWSTR lpName,
  1388. DWORD dwOpenMode,
  1389. DWORD dwPipeMode,
  1390. DWORD nMaxInstances,
  1391. DWORD nOutBufferSize,
  1392. DWORD nInBufferSize,
  1393. DWORD nDefaultTimeOut,
  1394. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  1395. BOOL TranslatePath
  1396. )
  1397. /*++
  1398. Parameters:
  1399. lpName --Supplies the pipe name Documented in "Pipe Names" section
  1400. earlier. This must be a local name.
  1401. dwOpenMode --Supplies the set of flags that define the mode which the
  1402. pipe is to be opened with. The open mode consists of access
  1403. flags (one of three values) logically ORed with a writethrough
  1404. flag (one of two values) and an overlapped flag (one of two
  1405. values), as described below.
  1406. dwOpenMode Flags:
  1407. PIPE_ACCESS_DUPLEX --Pipe is bidirectional. (This is
  1408. semantically equivalent to calling CreateFile with access
  1409. flags of GENERIC_READ | GENERIC_WRITE.)
  1410. PIPE_ACCESS_INBOUND --Data goes from client to server only.
  1411. (This is semantically equivalent to calling CreateFile with
  1412. access flags of GENERIC_READ.)
  1413. PIPE_ACCESS_OUTBOUND --Data goes from server to client only.
  1414. (This is semantically equivalent to calling CreateFile with
  1415. access flags of GENERIC_WRITE.)
  1416. PIPE_WRITETHROUGH --The redirector is not permitted to delay the
  1417. transmission of data to the named pipe buffer on the remote
  1418. server. This disables a performance enhancement for
  1419. applications that need synchronization with every write
  1420. operation.
  1421. FILE_FLAG_OVERLAPPED --Indicates that the system should
  1422. initialize the file so that ReadFile, WriteFile and other
  1423. operations that may take a significant time to process will
  1424. return ERROR_IO_PENDING. An event will be set to the
  1425. signalled state when the operation completes.
  1426. FILE_FLAG_WRITETHROUGH -- No intermediate buffering.
  1427. WRITE_DAC -- Standard security desired access
  1428. WRITE_OWNER -- ditto
  1429. ACCESS_SYSTEM_SECURITY -- ditto
  1430. dwPipeMode --Supplies the pipe-specific modes (as flags) of the pipe.
  1431. This parameter is a combination of a read-mode flag, a type flag,
  1432. and a wait flag.
  1433. dwPipeMode Flags:
  1434. PIPE_WAIT --Blocking mode is to be used for this handle.
  1435. PIPE_NOWAIT --Nonblocking mode is to be used for this handle.
  1436. PIPE_READMODE_BYTE --Read pipe as a byte stream.
  1437. PIPE_READMODE_MESSAGE --Read pipe as a message stream. Note that
  1438. this is not allowed with PIPE_TYPE_BYTE.
  1439. PIPE_TYPE_BYTE --Pipe is a byte-stream pipe. Note that this is
  1440. not allowed with PIPE_READMODE_MESSAGE.
  1441. PIPE_TYPE_MESSAGE --Pipe is a message-stream pipe.
  1442. nMaxInstances --Gives the maximum number of instances for this pipe.
  1443. Acceptable values are 1 to PIPE_UNLIMITED_INSTANCES-1 and
  1444. PIPE_UNLIMITED_INSTANCES.
  1445. nMaxInstances Special Values:
  1446. PIPE_UNLIMITED_INSTANCES --Unlimited instances of this pipe can
  1447. be created.
  1448. nOutBufferSize --Specifies an advisory on the number of bytes to
  1449. reserve for the outgoing buffer.
  1450. nInBufferSize --Specifies an advisory on the number of bytes to
  1451. reserve for the incoming buffer.
  1452. nDefaultTimeOut -- Specifies an optional pointer to a timeout value
  1453. that is to be used if a timeout value is not specified when
  1454. waiting for an instance of a named pipe. This parameter is only
  1455. meaningful when the first instance of a named pipe is created. If
  1456. neither CreateNamedPipe or WaitNamedPipe specify a timeout 50
  1457. milliseconds will be used.
  1458. lpSecurityAttributes --An optional parameter that, if present and
  1459. supported on the target system, supplies a security descriptor
  1460. for the named pipe. This parameter includes an inheritance flag
  1461. for the handle. If this parameter is not present, the handle is
  1462. not inherited by child processes.
  1463. Return Value:
  1464. Returns one of the following:
  1465. INVALID_HANDLE_VALUE --An error occurred. Call GetLastError for more
  1466. information.
  1467. Anything else --Returns a handle for use in the server side of
  1468. subsequent named pipe operations.
  1469. --*/
  1470. {
  1471. NTSTATUS Status;
  1472. OBJECT_ATTRIBUTES Obja;
  1473. HANDLE Handle;
  1474. UNICODE_STRING FileName;
  1475. IO_STATUS_BLOCK IoStatusBlock;
  1476. BOOLEAN TranslationStatus;
  1477. LARGE_INTEGER Timeout;
  1478. RTL_RELATIVE_NAME RelativeName;
  1479. PVOID FreeBuffer;
  1480. ULONG CreateFlags;
  1481. ULONG DesiredAccess;
  1482. ULONG ShareAccess;
  1483. ULONG MaxInstances;
  1484. SECURITY_DESCRIPTOR SecurityDescriptor;
  1485. PACL DefaultAcl = NULL;
  1486. if ((nMaxInstances == 0) ||
  1487. (nMaxInstances > PIPE_UNLIMITED_INSTANCES)) {
  1488. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  1489. return INVALID_HANDLE_VALUE;
  1490. }
  1491. // Convert Win32 maximum Instances to Nt maximum instances.
  1492. MaxInstances = (nMaxInstances == PIPE_UNLIMITED_INSTANCES)?
  1493. 0xffffffff : nMaxInstances;
  1494. if (TranslatePath)
  1495. {
  1496. TranslationStatus = RtlDosPathNameToNtPathName_U(
  1497. lpName,
  1498. &FileName,
  1499. NULL,
  1500. &RelativeName
  1501. );
  1502. if ( !TranslationStatus ) {
  1503. SetLastError(ERROR_PATH_NOT_FOUND);
  1504. return INVALID_HANDLE_VALUE;
  1505. }
  1506. FreeBuffer = FileName.Buffer;
  1507. if ( RelativeName.RelativeName.Length ) {
  1508. FileName = *(PUNICODE_STRING)&RelativeName.RelativeName;
  1509. }
  1510. else {
  1511. RelativeName.ContainingDirectory = NULL;
  1512. }
  1513. }
  1514. else
  1515. {
  1516. RtlInitUnicodeString(&FileName, lpName);
  1517. FreeBuffer = NULL;
  1518. RelativeName.ContainingDirectory = NULL;
  1519. }
  1520. InitializeObjectAttributes(
  1521. &Obja,
  1522. &FileName,
  1523. OBJ_CASE_INSENSITIVE,
  1524. RelativeName.ContainingDirectory,
  1525. NULL
  1526. );
  1527. if ( ARGUMENT_PRESENT(lpSecurityAttributes) ) {
  1528. Obja.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
  1529. if ( lpSecurityAttributes->bInheritHandle ) {
  1530. Obja.Attributes |= OBJ_INHERIT;
  1531. }
  1532. }
  1533. if (Obja.SecurityDescriptor == NULL) {
  1534. //
  1535. // Apply default security if none specified (bug 131090)
  1536. //
  1537. Status = RtlDefaultNpAcl( &DefaultAcl );
  1538. if (NT_SUCCESS( Status )) {
  1539. RtlCreateSecurityDescriptor( &SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
  1540. RtlSetDaclSecurityDescriptor( &SecurityDescriptor, TRUE, DefaultAcl, FALSE );
  1541. Obja.SecurityDescriptor = &SecurityDescriptor;
  1542. } else {
  1543. if (FreeBuffer != NULL)
  1544. {
  1545. RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
  1546. }
  1547. BaseSetLastNTError(Status);
  1548. return INVALID_HANDLE_VALUE;
  1549. }
  1550. }
  1551. // End of code common with fileopcr.c CreateFile()
  1552. CreateFlags = (dwOpenMode & FILE_FLAG_WRITE_THROUGH ? FILE_WRITE_THROUGH : 0 );
  1553. CreateFlags |= (dwOpenMode & FILE_FLAG_OVERLAPPED ? 0 : FILE_SYNCHRONOUS_IO_NONALERT);
  1554. //
  1555. // Determine the timeout. Convert from milliseconds to an Nt delta time
  1556. //
  1557. if ( nDefaultTimeOut ) {
  1558. Timeout.QuadPart = - (LONGLONG)UInt32x32To64( 10 * 1000, nDefaultTimeOut );
  1559. }
  1560. else {
  1561. // Default timeout is 50 Milliseconds
  1562. Timeout.QuadPart = -10 * 1000 * 50;
  1563. }
  1564. // Check no reserved bits are set by mistake.
  1565. if (( dwOpenMode & ~(PIPE_ACCESS_DUPLEX |
  1566. FILE_FLAG_OVERLAPPED | FILE_FLAG_WRITE_THROUGH |
  1567. FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC |
  1568. WRITE_OWNER | ACCESS_SYSTEM_SECURITY ))||
  1569. ( dwPipeMode & ~(PIPE_NOWAIT | PIPE_READMODE_MESSAGE |
  1570. PIPE_TYPE_MESSAGE ))) {
  1571. if (FreeBuffer != NULL)
  1572. {
  1573. RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
  1574. }
  1575. if (DefaultAcl != NULL) {
  1576. RtlFreeHeap(RtlProcessHeap(),0,DefaultAcl);
  1577. }
  1578. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  1579. return INVALID_HANDLE_VALUE;
  1580. }
  1581. //
  1582. // Translate the open mode into a sharemode to restrict the clients access
  1583. // and derive the appropriate local desired access.
  1584. //
  1585. switch ( dwOpenMode & PIPE_ACCESS_DUPLEX ) {
  1586. case PIPE_ACCESS_INBOUND:
  1587. ShareAccess = FILE_SHARE_WRITE;
  1588. DesiredAccess = GENERIC_READ;
  1589. break;
  1590. case PIPE_ACCESS_OUTBOUND:
  1591. ShareAccess = FILE_SHARE_READ;
  1592. DesiredAccess = GENERIC_WRITE;
  1593. break;
  1594. case PIPE_ACCESS_DUPLEX:
  1595. ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
  1596. DesiredAccess = GENERIC_READ | GENERIC_WRITE;
  1597. break;
  1598. default:
  1599. if (FreeBuffer != NULL)
  1600. {
  1601. RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
  1602. }
  1603. if (DefaultAcl != NULL) {
  1604. RtlFreeHeap(RtlProcessHeap(),0,DefaultAcl);
  1605. }
  1606. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  1607. return INVALID_HANDLE_VALUE;
  1608. }
  1609. DesiredAccess |= SYNCHRONIZE |
  1610. ( dwOpenMode & (WRITE_DAC | WRITE_OWNER | ACCESS_SYSTEM_SECURITY ));
  1611. Status = NtCreateNamedPipeFile (
  1612. &Handle,
  1613. DesiredAccess,
  1614. &Obja,
  1615. &IoStatusBlock,
  1616. ShareAccess,
  1617. (dwOpenMode & FILE_FLAG_FIRST_PIPE_INSTANCE) ?
  1618. FILE_CREATE : FILE_OPEN_IF, // Create first instance or subsequent
  1619. CreateFlags, // Create Options
  1620. dwPipeMode & PIPE_TYPE_MESSAGE ?
  1621. FILE_PIPE_MESSAGE_TYPE : FILE_PIPE_BYTE_STREAM_TYPE,
  1622. dwPipeMode & PIPE_READMODE_MESSAGE ?
  1623. FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE,
  1624. dwPipeMode & PIPE_NOWAIT ?
  1625. FILE_PIPE_COMPLETE_OPERATION : FILE_PIPE_QUEUE_OPERATION,
  1626. MaxInstances, // Max instances
  1627. nInBufferSize, // Inbound quota
  1628. nOutBufferSize, // Outbound quota
  1629. (PLARGE_INTEGER)&Timeout
  1630. );
  1631. if ( Status == STATUS_NOT_SUPPORTED ||
  1632. Status == STATUS_INVALID_DEVICE_REQUEST ) {
  1633. //
  1634. // The request must have been processed by some other device driver
  1635. // (other than NPFS). Map the error to something reasonable.
  1636. //
  1637. Status = STATUS_OBJECT_NAME_INVALID;
  1638. }
  1639. if (FreeBuffer != NULL)
  1640. {
  1641. RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
  1642. }
  1643. if (DefaultAcl != NULL) {
  1644. RtlFreeHeap(RtlProcessHeap(),0,DefaultAcl);
  1645. }
  1646. if ( !NT_SUCCESS(Status) ) {
  1647. BaseSetLastNTError(Status);
  1648. return INVALID_HANDLE_VALUE;
  1649. }
  1650. return Handle;
  1651. }
  1652. HANDLE
  1653. APIENTRY
  1654. NtNativeCreateNamedPipeA(
  1655. LPCSTR lpName,
  1656. DWORD dwOpenMode,
  1657. DWORD dwPipeMode,
  1658. DWORD nMaxInstances,
  1659. DWORD nOutBufferSize,
  1660. DWORD nInBufferSize,
  1661. DWORD nDefaultTimeOut,
  1662. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  1663. BOOL TranslatePath
  1664. )
  1665. /*++
  1666. Ansi thunk to CreateNamedPipeW.
  1667. --*/
  1668. {
  1669. NTSTATUS Status;
  1670. PUNICODE_STRING Unicode;
  1671. ANSI_STRING AnsiString;
  1672. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  1673. RtlInitAnsiString(&AnsiString,lpName);
  1674. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  1675. if ( !NT_SUCCESS(Status) ) {
  1676. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  1677. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  1678. }
  1679. else {
  1680. BaseSetLastNTError(Status);
  1681. }
  1682. return INVALID_HANDLE_VALUE;
  1683. }
  1684. return NtNativeCreateNamedPipeW(
  1685. (LPCWSTR)Unicode->Buffer,
  1686. dwOpenMode,
  1687. dwPipeMode,
  1688. nMaxInstances,
  1689. nOutBufferSize,
  1690. nInBufferSize,
  1691. nDefaultTimeOut,
  1692. lpSecurityAttributes,
  1693. TranslatePath);
  1694. }
  1695. BOOL
  1696. APIENTRY
  1697. ConnectNamedPipe(
  1698. HANDLE hNamedPipe,
  1699. LPOVERLAPPED lpOverlapped
  1700. )
  1701. /*++
  1702. Routine Description:
  1703. The ConnectNamedPipe function is used by the server side of a named pipe
  1704. to wait for a client to connect to the named pipe with a CreateFile
  1705. request. The handle provided with the call to ConnectNamedPipe must have
  1706. been previously returned by a successful call to CreateNamedPipe. The pipe
  1707. must be in the disconnected, listening or connected states for
  1708. ConnectNamedPipe to succeed.
  1709. The behavior of this call depends on the blocking/nonblocking mode selected
  1710. with the PIPE_WAIT/PIPE_NOWAIT flags when the server end of the pipe was
  1711. created with CreateNamedPipe.
  1712. If blocking mode is specified, ConnectNamedPipe will change the state from
  1713. disconnected to listening and block. When a client connects with a
  1714. CreateFile, the state will be changed from listening to connected and the
  1715. ConnectNamedPipe returns TRUE. When the file handle is created with
  1716. FILE_FLAG_OVERLAPPED on a blocking mode pipe, the lpOverlapped parameter
  1717. can be specified. This allows the caller to continue processing while the
  1718. ConnectNamedPipe API awaits a connection. When the pipe enters the
  1719. signalled state the event is set to the signalled state.
  1720. When nonblocking is specified ConnectNamedPipe will not block. On the
  1721. first call the state will change from disconnected to listening. When a
  1722. client connects with an Open the state will be changed from listening to
  1723. connected. The ConnectNamedPipe will return FALSE (with GetLastError
  1724. returning ERROR_PIPE_LISTENING) until the state is changed to the listening
  1725. state.
  1726. Arguments:
  1727. hNamedPipe - Supplies a Handle to the server side of a named pipe.
  1728. lpOverlapped - Supplies an overlap structure to be used with the request.
  1729. If NULL then the API will not return until the operation completes. When
  1730. FILE_FLAG_OVERLAPPED is specified when the handle was created,
  1731. ConnectNamedPipe may return ERROR_IO_PENDING to allow the caller to
  1732. continue processing while the operation completes. The event (or File
  1733. handle if hEvent=NULL) will be set to the not signalled state before
  1734. ERROR_IO_PENDING is returned. The event will be set to the signalled
  1735. state upon completion of the request. GetOverlappedResult is used to
  1736. determine the error status.
  1737. Return Value:
  1738. TRUE -- The operation was successful, the pipe is in the
  1739. connected state.
  1740. FALSE -- The operation failed. Extended error status is available using
  1741. GetLastError.
  1742. --*/
  1743. {
  1744. NTSTATUS Status;
  1745. IO_STATUS_BLOCK Iosb;
  1746. if ( lpOverlapped ) {
  1747. lpOverlapped->Internal = (DWORD)STATUS_PENDING;
  1748. }
  1749. Status = NtFsControlFile(
  1750. hNamedPipe,
  1751. (lpOverlapped==NULL)? NULL : lpOverlapped->hEvent,
  1752. NULL, // ApcRoutine
  1753. lpOverlapped ? ((ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped) : NULL,
  1754. (lpOverlapped==NULL) ? &Iosb : (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  1755. FSCTL_PIPE_LISTEN,
  1756. NULL, // InputBuffer
  1757. 0, // InputBufferLength,
  1758. NULL, // OutputBuffer
  1759. 0 // OutputBufferLength
  1760. );
  1761. if ( lpOverlapped == NULL && Status == STATUS_PENDING) {
  1762. // Operation must complete before return & Iosb destroyed
  1763. Status = NtWaitForSingleObject( hNamedPipe, FALSE, NULL );
  1764. if ( NT_SUCCESS(Status)) {
  1765. Status = Iosb.Status;
  1766. }
  1767. }
  1768. if (NT_SUCCESS( Status ) && Status != STATUS_PENDING ) {
  1769. return TRUE;
  1770. }
  1771. else
  1772. {
  1773. BaseSetLastNTError(Status);
  1774. return FALSE;
  1775. }
  1776. }
  1777. BOOL
  1778. APIENTRY
  1779. WaitNamedPipeA(
  1780. LPCSTR lpNamedPipeName,
  1781. DWORD nTimeOut
  1782. )
  1783. /*++
  1784. Ansi thunk to WaitNamedPipeW
  1785. --*/
  1786. {
  1787. ANSI_STRING Ansi;
  1788. UNICODE_STRING UnicodeString;
  1789. BOOL b;
  1790. RtlInitAnsiString(&Ansi, lpNamedPipeName);
  1791. if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeString, &Ansi, TRUE))) {
  1792. return FALSE;
  1793. }
  1794. b = WaitNamedPipeW( UnicodeString.Buffer, nTimeOut );
  1795. RtlFreeUnicodeString(&UnicodeString);
  1796. return b;
  1797. }
  1798. BOOL
  1799. APIENTRY
  1800. WaitNamedPipeW(
  1801. LPCWSTR lpNamedPipeName,
  1802. DWORD nTimeOut
  1803. )
  1804. /*++
  1805. Routine Description:
  1806. The WaitNamedPipe function waits for a named pipe to become available.
  1807. Arguments:
  1808. lpNamedPipeName - Supplies the name of the named pipe.
  1809. nTimeOut - Gives a value (in milliseconds) that is the amount of time
  1810. this function should wait for the pipe to become available. (Note
  1811. that the function may take longer than that to execute, due to
  1812. various factors.)
  1813. nTimeOut Special Values:
  1814. NMPWAIT_WAIT_FOREVER
  1815. No timeout.
  1816. NMPWAIT_USE_DEFAULT_WAIT
  1817. Use default timeout set in call to CreateNamedPipe.
  1818. Return Value:
  1819. TRUE -- The operation was successful.
  1820. FALSE -- The operation failed. Extended error status is available using
  1821. GetLastError.
  1822. --*/
  1823. {
  1824. IO_STATUS_BLOCK Iosb;
  1825. OBJECT_ATTRIBUTES Obja;
  1826. NTSTATUS Status;
  1827. RTL_PATH_TYPE PathType;
  1828. ULONG WaitPipeLength;
  1829. PFILE_PIPE_WAIT_FOR_BUFFER WaitPipe;
  1830. PWSTR FreeBuffer;
  1831. UNICODE_STRING FileSystem;
  1832. UNICODE_STRING PipeName;
  1833. UNICODE_STRING OriginalPipeName;
  1834. UNICODE_STRING ValidUnicodePrefix;
  1835. HANDLE Handle;
  1836. IO_STATUS_BLOCK IoStatusBlock;
  1837. LPWSTR Pwc;
  1838. ULONG Index;
  1839. //
  1840. // Open a handle either to the redirector or the NPFS depending on
  1841. // the start of the pipe name. Split lpNamedPipeName into two
  1842. // halves as follows:
  1843. // \\.\pipe\pipename \\.\pipe\ and pipename
  1844. // \\server\pipe\pipename \\ and server\pipe\pipename
  1845. //
  1846. if (!RtlCreateUnicodeString( &OriginalPipeName, lpNamedPipeName)) {
  1847. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1848. return FALSE;
  1849. }
  1850. //
  1851. // Change all the forward slashes into backward slashes.
  1852. //
  1853. for ( Index =0; Index < (OriginalPipeName.Length/sizeof(WCHAR)); Index++ ) {
  1854. if (OriginalPipeName.Buffer[Index] == L'/') {
  1855. OriginalPipeName.Buffer[Index] = L'\\';
  1856. }
  1857. }
  1858. PipeName = OriginalPipeName;
  1859. PathType = RtlDetermineDosPathNameType_U(lpNamedPipeName);
  1860. FreeBuffer = NULL;
  1861. switch ( PathType ) {
  1862. case RtlPathTypeLocalDevice:
  1863. // Name should be of the form \\.\pipe\pipename (IgnoreCase)
  1864. RtlInitUnicodeString( &ValidUnicodePrefix, DOS_LOCAL_PIPE_PREFIX);
  1865. if (RtlPrefixString((PSTRING)&ValidUnicodePrefix,
  1866. (PSTRING)&PipeName,
  1867. TRUE) == FALSE) {
  1868. RtlFreeUnicodeString(&OriginalPipeName);
  1869. BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
  1870. return FALSE;
  1871. }
  1872. // Skip first 9 characters "\\.\pipe\"
  1873. PipeName.Buffer+=9;
  1874. PipeName.Length-=9*sizeof(WCHAR);
  1875. RtlInitUnicodeString( &FileSystem, DOS_LOCAL_PIPE);
  1876. break;
  1877. case RtlPathTypeUncAbsolute:
  1878. // Name is of the form \\server\pipe\pipename
  1879. // Find the pipe name.
  1880. for ( Pwc = &PipeName.Buffer[2]; *Pwc != 0; Pwc++) {
  1881. if ( *Pwc == L'\\') {
  1882. // Found backslash after servername
  1883. break;
  1884. }
  1885. }
  1886. if ( (*Pwc != 0) &&
  1887. ( _wcsnicmp( Pwc + 1, L"pipe\\", 5 ) == 0 ) ) {
  1888. // Temporarily, break this up into 2 strings
  1889. // string1 = \\server\pipe
  1890. // string2 = the-rest
  1891. Pwc += (sizeof (L"pipe\\") / sizeof( WCHAR ) ) - 1;
  1892. } else {
  1893. // This is not a valid remote path name.
  1894. RtlFreeUnicodeString(&OriginalPipeName);
  1895. BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
  1896. return FALSE;
  1897. }
  1898. // Pwc now points to the first path seperator after \\server\pipe.
  1899. // Attempt to open \DosDevices\Unc\Servername\Pipe.
  1900. PipeName.Buffer = &PipeName.Buffer[2];
  1901. PipeName.Length = (USHORT)((PCHAR)Pwc - (PCHAR)PipeName.Buffer);
  1902. PipeName.MaximumLength = PipeName.Length;
  1903. FileSystem.MaximumLength =
  1904. (USHORT)sizeof( DOS_REMOTE_PIPE ) +
  1905. PipeName.MaximumLength;
  1906. FileSystem.Buffer = (PWSTR)RtlAllocateHeap(
  1907. RtlProcessHeap(), 0,
  1908. FileSystem.MaximumLength
  1909. );
  1910. if ( !FileSystem.Buffer ) {
  1911. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1912. RtlFreeUnicodeString(&OriginalPipeName);
  1913. return FALSE;
  1914. }
  1915. FreeBuffer = FileSystem.Buffer;
  1916. RtlCopyMemory(
  1917. FileSystem.Buffer,
  1918. DOS_REMOTE_PIPE,
  1919. sizeof( DOS_REMOTE_PIPE ) - sizeof(WCHAR)
  1920. );
  1921. FileSystem.Length = sizeof( DOS_REMOTE_PIPE ) - sizeof(WCHAR);
  1922. RtlAppendUnicodeStringToString( &FileSystem, &PipeName );
  1923. // Set up pipe name, skip leading backslashes.
  1924. RtlInitUnicodeString( &PipeName, (PWCH)Pwc + 1 );
  1925. break;
  1926. default:
  1927. BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
  1928. RtlFreeUnicodeString(&OriginalPipeName);
  1929. return FALSE;
  1930. }
  1931. InitializeObjectAttributes(
  1932. &Obja,
  1933. &FileSystem,
  1934. OBJ_CASE_INSENSITIVE,
  1935. NULL,
  1936. NULL
  1937. );
  1938. Status = NtOpenFile(
  1939. &Handle,
  1940. (ACCESS_MASK)FILE_READ_ATTRIBUTES | SYNCHRONIZE,
  1941. &Obja,
  1942. &IoStatusBlock,
  1943. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1944. FILE_SYNCHRONOUS_IO_NONALERT
  1945. );
  1946. if (FreeBuffer != NULL) {
  1947. RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
  1948. }
  1949. if ( !NT_SUCCESS(Status) ) {
  1950. RtlFreeUnicodeString(&OriginalPipeName);
  1951. BaseSetLastNTError(Status);
  1952. return FALSE;
  1953. }
  1954. WaitPipeLength =
  1955. FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name[0]) + PipeName.Length;
  1956. WaitPipe = (PFILE_PIPE_WAIT_FOR_BUFFER)
  1957. RtlAllocateHeap(RtlProcessHeap(), 0, WaitPipeLength);
  1958. if ( !WaitPipe ) {
  1959. RtlFreeUnicodeString(&OriginalPipeName);
  1960. NtClose(Handle);
  1961. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1962. return FALSE;
  1963. }
  1964. if ( nTimeOut == NMPWAIT_USE_DEFAULT_WAIT ) {
  1965. WaitPipe->TimeoutSpecified = FALSE;
  1966. }
  1967. else {
  1968. if ( nTimeOut == NMPWAIT_WAIT_FOREVER ) {
  1969. WaitPipe->Timeout.LowPart = 0;
  1970. WaitPipe->Timeout.HighPart =0x80000000;
  1971. }
  1972. else {
  1973. //
  1974. // Convert from milliseconds to an Nt delta time.
  1975. //
  1976. WaitPipe->Timeout.QuadPart =
  1977. - (LONGLONG)UInt32x32To64( 10 * 1000, nTimeOut );
  1978. }
  1979. WaitPipe->TimeoutSpecified = TRUE;
  1980. }
  1981. WaitPipe->NameLength = PipeName.Length;
  1982. RtlCopyMemory(
  1983. WaitPipe->Name,
  1984. PipeName.Buffer,
  1985. PipeName.Length
  1986. );
  1987. RtlFreeUnicodeString(&OriginalPipeName);
  1988. Status = NtFsControlFile(Handle,
  1989. NULL,
  1990. NULL, // APC routine
  1991. NULL, // APC Context
  1992. &Iosb,
  1993. FSCTL_PIPE_WAIT,// IoControlCode
  1994. WaitPipe, // Buffer for data to the FS
  1995. WaitPipeLength,
  1996. NULL, // OutputBuffer for data from the FS
  1997. 0 // OutputBuffer Length
  1998. );
  1999. RtlFreeHeap(RtlProcessHeap(),0,WaitPipe);
  2000. NtClose(Handle);
  2001. if (NT_SUCCESS( Status ) ) {
  2002. return TRUE;
  2003. }
  2004. else
  2005. {
  2006. BaseSetLastNTError(Status);
  2007. return FALSE;
  2008. }
  2009. }
  2010. DWORD
  2011. WaitForSingleObject(
  2012. HANDLE hHandle,
  2013. DWORD dwMilliseconds
  2014. )
  2015. /*++
  2016. Routine Description:
  2017. A wait operation on a waitable object is accomplished with the
  2018. WaitForSingleObject function.
  2019. Waiting on an object checks the current state of the object. If the
  2020. current state of the object allows continued execution, any
  2021. adjustments to the object state are made (for example, decrementing
  2022. the semaphore count for a semaphore object) and the thread continues
  2023. execution. If the current state of the object does not allow
  2024. continued execution, the thread is placed into the wait state
  2025. pending the change of the object's state or time-out.
  2026. Arguments:
  2027. hHandle - An open handle to a waitable object. The handle must have
  2028. SYNCHRONIZE access to the object.
  2029. dwMilliseconds - A time-out value that specifies the relative time,
  2030. in milliseconds, over which the wait is to be completed. A
  2031. timeout value of 0 specified that the wait is to timeout
  2032. immediately. This allows an application to test an object to
  2033. determine if it is in the signaled state. A timeout value of -1
  2034. specifies an infinite timeout period.
  2035. Return Value:
  2036. WAIT_TIME_OUT - Indicates that the wait was terminated due to the
  2037. TimeOut conditions.
  2038. 0 - indicates the specified object attained a Signaled
  2039. state thus completing the wait.
  2040. WAIT_ABANDONED - indicates the specified object attained a Signaled
  2041. state but was abandoned.
  2042. --*/
  2043. {
  2044. return WaitForSingleObjectEx(hHandle,dwMilliseconds,FALSE);
  2045. }
  2046. DWORD
  2047. APIENTRY
  2048. WaitForSingleObjectEx(
  2049. HANDLE hHandle,
  2050. DWORD dwMilliseconds,
  2051. BOOL bAlertable
  2052. )
  2053. /*++
  2054. Routine Description:
  2055. A wait operation on a waitable object is accomplished with the
  2056. WaitForSingleObjectEx function.
  2057. Waiting on an object checks the current state of the object. If the
  2058. current state of the object allows continued execution, any
  2059. adjustments to the object state are made (for example, decrementing
  2060. the semaphore count for a semaphore object) and the thread continues
  2061. execution. If the current state of the object does not allow
  2062. continued execution, the thread is placed into the wait state
  2063. pending the change of the object's state or time-out.
  2064. If the bAlertable parameter is FALSE, the only way the wait
  2065. terminates is because the specified timeout period expires, or
  2066. because the specified object entered the signaled state. If the
  2067. bAlertable parameter is TRUE, then the wait can return due to any
  2068. one of the above wait termination conditions, or because an I/O
  2069. completion callback terminated the wait early (return value of
  2070. WAIT_IO_COMPLETION).
  2071. Arguments:
  2072. hHandle - An open handle to a waitable object. The handle must have
  2073. SYNCHRONIZE access to the object.
  2074. dwMilliseconds - A time-out value that specifies the relative time,
  2075. in milliseconds, over which the wait is to be completed. A
  2076. timeout value of 0 specified that the wait is to timeout
  2077. immediately. This allows an application to test an object to
  2078. determine if it is in the signaled state. A timeout value of
  2079. 0xffffffff specifies an infinite timeout period.
  2080. bAlertable - Supplies a flag that controls whether or not the
  2081. wait may terminate early due to an I/O completion callback.
  2082. A value of TRUE allows this API to complete early due to an I/O
  2083. completion callback. A value of FALSE will not allow I/O
  2084. completion callbacks to terminate this call early.
  2085. Return Value:
  2086. WAIT_TIME_OUT - Indicates that the wait was terminated due to the
  2087. TimeOut conditions.
  2088. 0 - indicates the specified object attained a Signaled
  2089. state thus completing the wait.
  2090. 0xffffffff - The wait terminated due to an error. GetLastError may be
  2091. used to get additional error information.
  2092. WAIT_ABANDONED - indicates the specified object attained a Signaled
  2093. state but was abandoned.
  2094. WAIT_IO_COMPLETION - The wait terminated due to one or more I/O
  2095. completion callbacks.
  2096. --*/
  2097. {
  2098. NTSTATUS Status;
  2099. LARGE_INTEGER TimeOut;
  2100. PLARGE_INTEGER pTimeOut;
  2101. PPEB Peb;
  2102. RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME Frame = { sizeof(Frame), RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER };
  2103. RtlActivateActivationContextUnsafeFast(&Frame, NULL); // make the process default activation context active so that APCs are delivered under it
  2104. __try {
  2105. if (dwMilliseconds == INFINITE)
  2106. {
  2107. pTimeOut = NULL;
  2108. }
  2109. else
  2110. {
  2111. Win32ToNtTimeout(dwMilliseconds, &TimeOut);
  2112. pTimeOut = &TimeOut;
  2113. }
  2114. rewait:
  2115. Status = NtWaitForSingleObject(hHandle,(BOOLEAN)bAlertable,pTimeOut);
  2116. if ( !NT_SUCCESS(Status) ) {
  2117. BaseSetLastNTError(Status);
  2118. Status = (NTSTATUS)0xffffffff;
  2119. }
  2120. else {
  2121. if ( bAlertable && Status == STATUS_ALERTED ) {
  2122. goto rewait;
  2123. }
  2124. }
  2125. } __finally {
  2126. RtlDeactivateActivationContextUnsafeFast(&Frame);
  2127. }
  2128. return (DWORD)Status;
  2129. }
  2130. DWORD
  2131. WaitForMultipleObjects(
  2132. DWORD nCount,
  2133. CONST HANDLE *lpHandles,
  2134. BOOL bWaitAll,
  2135. DWORD dwMilliseconds
  2136. )
  2137. /*++
  2138. Routine Description:
  2139. A wait operation on multiple waitable objects (up to
  2140. MAXIMUM_WAIT_OBJECTS) is accomplished with the WaitForMultipleObjects
  2141. function.
  2142. Arguments:
  2143. nCount - A count of the number of objects that are to be waited on.
  2144. lpHandles - An array of object handles. Each handle must have
  2145. SYNCHRONIZE access to the associated object.
  2146. bWaitAll - A flag that supplies the wait type. A value of TRUE
  2147. indicates a "wait all". A value of false indicates a "wait
  2148. any".
  2149. dwMilliseconds - A time-out value that specifies the relative time,
  2150. in milliseconds, over which the wait is to be completed. A
  2151. timeout value of 0 specified that the wait is to timeout
  2152. immediately. This allows an application to test an object to
  2153. determine if it is in the signaled state. A timeout value of -1
  2154. specifies an infinite timeout period.
  2155. Return Value:
  2156. WAIT_TIME_OUT - indicates that the wait was terminated due to the
  2157. TimeOut conditions.
  2158. 0 to MAXIMUM_WAIT_OBJECTS-1, indicates, in the case of wait for any
  2159. object, the object number which satisfied the wait. In the case
  2160. of wait for all objects, the value only indicates that the wait
  2161. was completed successfully.
  2162. WAIT_ABANDONED_0 to (WAIT_ABANDONED_0)+(MAXIMUM_WAIT_OBJECTS - 1),
  2163. indicates, in the case of wait for any object, the object number
  2164. which satisfied the event, and that the object which satisfied
  2165. the event was abandoned. In the case of wait for all objects,
  2166. the value indicates that the wait was completed successfully and
  2167. at least one of the objects was abandoned.
  2168. --*/
  2169. {
  2170. return WaitForMultipleObjectsEx(nCount,lpHandles,bWaitAll,dwMilliseconds,FALSE);
  2171. }
  2172. DWORD
  2173. APIENTRY
  2174. WaitForMultipleObjectsEx(
  2175. DWORD nCount,
  2176. CONST HANDLE *lpHandles,
  2177. BOOL bWaitAll,
  2178. DWORD dwMilliseconds,
  2179. BOOL bAlertable
  2180. )
  2181. /*++
  2182. Routine Description:
  2183. A wait operation on multiple waitable objects (up to
  2184. MAXIMUM_WAIT_OBJECTS) is accomplished with the
  2185. WaitForMultipleObjects function.
  2186. This API can be used to wait on any of the specified objects to
  2187. enter the signaled state, or all of the objects to enter the
  2188. signaled state.
  2189. If the bAlertable parameter is FALSE, the only way the wait
  2190. terminates is because the specified timeout period expires, or
  2191. because the specified objects entered the signaled state. If the
  2192. bAlertable parameter is TRUE, then the wait can return due to any one of
  2193. the above wait termination conditions, or because an I/O completion
  2194. callback terminated the wait early (return value of
  2195. WAIT_IO_COMPLETION).
  2196. Arguments:
  2197. nCount - A count of the number of objects that are to be waited on.
  2198. lpHandles - An array of object handles. Each handle must have
  2199. SYNCHRONIZE access to the associated object.
  2200. bWaitAll - A flag that supplies the wait type. A value of TRUE
  2201. indicates a "wait all". A value of false indicates a "wait
  2202. any".
  2203. dwMilliseconds - A time-out value that specifies the relative time,
  2204. in milliseconds, over which the wait is to be completed. A
  2205. timeout value of 0 specified that the wait is to timeout
  2206. immediately. This allows an application to test an object to
  2207. determine if it is in the signaled state. A timeout value of
  2208. 0xffffffff specifies an infinite timeout period.
  2209. bAlertable - Supplies a flag that controls whether or not the
  2210. wait may terminate early due to an I/O completion callback.
  2211. A value of TRUE allows this API to complete early due to an I/O
  2212. completion callback. A value of FALSE will not allow I/O
  2213. completion callbacks to terminate this call early.
  2214. Return Value:
  2215. WAIT_TIME_OUT - indicates that the wait was terminated due to the
  2216. TimeOut conditions.
  2217. 0 to MAXIMUM_WAIT_OBJECTS-1, indicates, in the case of wait for any
  2218. object, the object number which satisfied the wait. In the case
  2219. of wait for all objects, the value only indicates that the wait
  2220. was completed successfully.
  2221. 0xffffffff - The wait terminated due to an error. GetLastError may be
  2222. used to get additional error information.
  2223. WAIT_ABANDONED_0 to (WAIT_ABANDONED_0)+(MAXIMUM_WAIT_OBJECTS - 1),
  2224. indicates, in the case of wait for any object, the object number
  2225. which satisfied the event, and that the object which satisfied
  2226. the event was abandoned. In the case of wait for all objects,
  2227. the value indicates that the wait was completed successfully and
  2228. at least one of the objects was abandoned.
  2229. WAIT_IO_COMPLETION - The wait terminated due to one or more I/O
  2230. completion callbacks.
  2231. --*/
  2232. {
  2233. NTSTATUS Status;
  2234. LARGE_INTEGER TimeOut;
  2235. PLARGE_INTEGER pTimeOut;
  2236. DWORD i;
  2237. LPHANDLE HandleArray;
  2238. HANDLE Handles[ 8 ];
  2239. PPEB Peb;
  2240. RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME Frame = { sizeof(Frame), RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER };
  2241. RtlActivateActivationContextUnsafeFast(&Frame, NULL); // make the process default activation context active so that APCs are delivered under it
  2242. __try {
  2243. if (nCount > 8) {
  2244. BaseSetLastNTError(STATUS_NO_MEMORY);
  2245. return 0xffffffff;
  2246. } else {
  2247. HandleArray = Handles;
  2248. }
  2249. RtlCopyMemory(HandleArray,(LPVOID)lpHandles,nCount*sizeof(HANDLE));
  2250. Peb = NtCurrentPeb();
  2251. if (dwMilliseconds == INFINITE)
  2252. {
  2253. pTimeOut = NULL;
  2254. }
  2255. else
  2256. {
  2257. Win32ToNtTimeout(dwMilliseconds, &TimeOut);
  2258. pTimeOut = &TimeOut;
  2259. }
  2260. rewait:
  2261. Status = NtWaitForMultipleObjects(
  2262. (CHAR)nCount,
  2263. HandleArray,
  2264. bWaitAll ? WaitAll : WaitAny,
  2265. (BOOLEAN)bAlertable,
  2266. pTimeOut
  2267. );
  2268. if ( !NT_SUCCESS(Status) ) {
  2269. BaseSetLastNTError(Status);
  2270. Status = (NTSTATUS)0xffffffff;
  2271. }
  2272. else {
  2273. if ( bAlertable && Status == STATUS_ALERTED ) {
  2274. goto rewait;
  2275. }
  2276. }
  2277. if (HandleArray != Handles) {
  2278. RtlFreeHeap(RtlProcessHeap(), 0, HandleArray);
  2279. }
  2280. } __finally {
  2281. RtlDeactivateActivationContextUnsafeFast(&Frame);
  2282. }
  2283. return (DWORD)Status;
  2284. }
  2285. HANDLE
  2286. APIENTRY
  2287. CreateEventA(
  2288. LPSECURITY_ATTRIBUTES lpEventAttributes,
  2289. BOOL bManualReset,
  2290. BOOL bInitialState,
  2291. LPCSTR lpName
  2292. )
  2293. /*++
  2294. Routine Description:
  2295. ANSI thunk to CreateEventW
  2296. --*/
  2297. {
  2298. PUNICODE_STRING Unicode;
  2299. ANSI_STRING AnsiString;
  2300. NTSTATUS Status;
  2301. LPCWSTR NameBuffer;
  2302. NameBuffer = NULL;
  2303. if ( ARGUMENT_PRESENT(lpName) ) {
  2304. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  2305. RtlInitAnsiString(&AnsiString,lpName);
  2306. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  2307. if ( !NT_SUCCESS(Status) ) {
  2308. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  2309. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  2310. }
  2311. else {
  2312. BaseSetLastNTError(Status);
  2313. }
  2314. return NULL;
  2315. }
  2316. NameBuffer = (LPCWSTR)Unicode->Buffer;
  2317. }
  2318. return CreateEventW(
  2319. lpEventAttributes,
  2320. bManualReset,
  2321. bInitialState,
  2322. NameBuffer
  2323. );
  2324. }
  2325. HANDLE
  2326. APIENTRY
  2327. CreateEventW(
  2328. LPSECURITY_ATTRIBUTES lpEventAttributes,
  2329. BOOL bManualReset,
  2330. BOOL bInitialState,
  2331. LPCWSTR lpName
  2332. )
  2333. /*++
  2334. Routine Description:
  2335. An event object is created and a handle opened for access to the
  2336. object with the CreateEvent function.
  2337. The CreateEvent function creates an event object with the specified
  2338. initial state. If an event is in the Signaled state (TRUE), a wait
  2339. operation on the event does not block. If the event is in the Not-
  2340. Signaled state (FALSE), a wait operation on the event blocks until
  2341. the specified event attains a state of Signaled, or the timeout
  2342. value is exceeded.
  2343. In addition to the STANDARD_RIGHTS_REQUIRED access flags, the following
  2344. object type specific access flags are valid for event objects:
  2345. - EVENT_MODIFY_STATE - Modify state access (set and reset) to
  2346. the event is desired.
  2347. - SYNCHRONIZE - Synchronization access (wait) to the event is
  2348. desired.
  2349. - EVENT_ALL_ACCESS - This set of access flags specifies all of
  2350. the possible access flags for an event object.
  2351. Arguments:
  2352. lpEventAttributes - An optional parameter that may be used to
  2353. specify the attributes of the new event. If the parameter is
  2354. not specified, then the event is created without a security
  2355. descriptor, and the resulting handle is not inherited on process
  2356. creation.
  2357. bManualReset - Supplies a flag which if TRUE specifies that the
  2358. event must be manually reset. If the value is FALSE, then after
  2359. releasing a single waiter, the system automaticaly resets the
  2360. event.
  2361. bInitialState - The initial state of the event object, one of TRUE
  2362. or FALSE. If the InitialState is specified as TRUE, the event's
  2363. current state value is set to one, otherwise it is set to zero.
  2364. lpName - Optional unicode name of event
  2365. Return Value:
  2366. NON-NULL - Returns a handle to the new event. The handle has full
  2367. access to the new event and may be used in any API that requires
  2368. a handle to an event object.
  2369. FALSE/NULL - The operation failed. Extended error status is available
  2370. using GetLastError.
  2371. --*/
  2372. {
  2373. NTSTATUS Status;
  2374. OBJECT_ATTRIBUTES Obja;
  2375. POBJECT_ATTRIBUTES pObja;
  2376. HANDLE Handle;
  2377. UNICODE_STRING ObjectName;
  2378. PWCHAR pstrNewObjName = NULL;
  2379. if (lpName != NULL || lpEventAttributes != NULL)
  2380. {
  2381. return FALSE;
  2382. }
  2383. pObja = NULL;
  2384. Status = NtCreateEvent(
  2385. &Handle,
  2386. EVENT_ALL_ACCESS,
  2387. pObja,
  2388. bManualReset ? NotificationEvent : SynchronizationEvent,
  2389. (BOOLEAN)bInitialState
  2390. );
  2391. if (pstrNewObjName) {
  2392. RtlFreeHeap(RtlProcessHeap(), 0, pstrNewObjName);
  2393. }
  2394. if ( NT_SUCCESS(Status) ) {
  2395. if ( Status == STATUS_OBJECT_NAME_EXISTS ) {
  2396. SetLastError(ERROR_ALREADY_EXISTS);
  2397. }
  2398. else {
  2399. SetLastError(0);
  2400. }
  2401. return Handle;
  2402. }
  2403. else {
  2404. BaseSetLastNTError(Status);
  2405. return NULL;
  2406. }
  2407. }
  2408. BOOL
  2409. SetEvent(
  2410. HANDLE hEvent
  2411. )
  2412. /*++
  2413. Routine Description:
  2414. An event can be set to the signaled state (TRUE) with the SetEvent
  2415. function.
  2416. Setting the event causes the event to attain a state of Signaled,
  2417. which releases all currently waiting threads (for manual reset
  2418. events), or a single waiting thread (for automatic reset events).
  2419. Arguments:
  2420. hEvent - Supplies an open handle to an event object. The
  2421. handle must have EVENT_MODIFY_STATE access to the event.
  2422. Return Value:
  2423. TRUE - The operation was successful
  2424. FALSE/NULL - The operation failed. Extended error status is available
  2425. using GetLastError.
  2426. --*/
  2427. {
  2428. NTSTATUS Status;
  2429. Status = NtSetEvent(hEvent,NULL);
  2430. if ( NT_SUCCESS(Status) ) {
  2431. return TRUE;
  2432. }
  2433. else {
  2434. BaseSetLastNTError(Status);
  2435. return FALSE;
  2436. }
  2437. }
  2438. BOOL
  2439. ResetEvent(
  2440. HANDLE hEvent
  2441. )
  2442. /*++
  2443. Routine Description:
  2444. The state of an event is set to the Not-Signaled state (FALSE) using
  2445. the ClearEvent function.
  2446. Once the event attains a state of Not-Signaled, any threads which
  2447. wait on the event block, awaiting the event to become Signaled. The
  2448. reset event service sets the event count to zero for the state of
  2449. the event.
  2450. Arguments:
  2451. hEvent - Supplies an open handle to an event object. The
  2452. handle must have EVENT_MODIFY_STATE access to the event.
  2453. Return Value:
  2454. TRUE - The operation was successful
  2455. FALSE/NULL - The operation failed. Extended error status is available
  2456. using GetLastError.
  2457. --*/
  2458. {
  2459. NTSTATUS Status;
  2460. Status = NtClearEvent(hEvent);
  2461. if ( NT_SUCCESS(Status) ) {
  2462. return TRUE;
  2463. }
  2464. else {
  2465. BaseSetLastNTError(Status);
  2466. return FALSE;
  2467. }
  2468. }
  2469. BOOL
  2470. WINAPI
  2471. GetOverlappedResult(
  2472. HANDLE hFile,
  2473. LPOVERLAPPED lpOverlapped,
  2474. LPDWORD lpNumberOfBytesTransferred,
  2475. BOOL bWait
  2476. )
  2477. /*++
  2478. Routine Description:
  2479. The GetOverlappedResult function returns the result of the last
  2480. operation that used lpOverlapped and returned ERROR_IO_PENDING.
  2481. Arguments:
  2482. hFile - Supplies the open handle to the file that the overlapped
  2483. structure lpOverlapped was supplied to ReadFile, WriteFile,
  2484. ConnectNamedPipe, WaitNamedPipe or TransactNamedPipe.
  2485. lpOverlapped - Points to an OVERLAPPED structure previously supplied to
  2486. ReadFile, WriteFile, ConnectNamedPipe, WaitNamedPipe or
  2487. TransactNamedPipe.
  2488. lpNumberOfBytesTransferred - Returns the number of bytes transferred
  2489. by the operation.
  2490. bWait - A boolean value that affects the behavior when the operation
  2491. is still in progress. If TRUE and the operation is still in progress,
  2492. GetOverlappedResult will wait for the operation to complete before
  2493. returning. If FALSE and the operation is incomplete,
  2494. GetOverlappedResult will return FALSE. In this case the extended
  2495. error information available from the GetLastError function will be
  2496. set to ERROR_IO_INCOMPLETE.
  2497. Return Value:
  2498. TRUE -- The operation was successful, the pipe is in the
  2499. connected state.
  2500. FALSE -- The operation failed. Extended error status is available using
  2501. GetLastError.
  2502. --*/
  2503. {
  2504. DWORD WaitReturn;
  2505. //
  2506. // Did caller specify an event to the original operation or was the
  2507. // default (file handle) used?
  2508. //
  2509. if (lpOverlapped->Internal == (DWORD)STATUS_PENDING ) {
  2510. if ( bWait ) {
  2511. WaitReturn = WaitForSingleObject(
  2512. ( lpOverlapped->hEvent != NULL ) ?
  2513. lpOverlapped->hEvent : hFile,
  2514. INFINITE
  2515. );
  2516. }
  2517. else {
  2518. WaitReturn = WAIT_TIMEOUT;
  2519. }
  2520. if ( WaitReturn == WAIT_TIMEOUT ) {
  2521. // !bWait and event in not signalled state
  2522. SetLastError( ERROR_IO_INCOMPLETE );
  2523. return FALSE;
  2524. }
  2525. if ( WaitReturn != 0 ) {
  2526. return FALSE; // WaitForSingleObject calls BaseSetLastError
  2527. }
  2528. }
  2529. *lpNumberOfBytesTransferred = (DWORD)lpOverlapped->InternalHigh;
  2530. if ( NT_SUCCESS((NTSTATUS)lpOverlapped->Internal) ){
  2531. return TRUE;
  2532. }
  2533. else {
  2534. BaseSetLastNTError( (NTSTATUS)lpOverlapped->Internal );
  2535. return FALSE;
  2536. }
  2537. }
  2538. BOOL
  2539. ClearCommError(
  2540. HANDLE hFile,
  2541. LPDWORD lpErrors,
  2542. LPCOMSTAT lpStat
  2543. )
  2544. /*++
  2545. Routine Description:
  2546. In case of a communications error, such as a buffer overrun or
  2547. framing error, the communications software will abort all
  2548. read and write operations on the communication port. No further
  2549. read or write operations will be accepted until this function
  2550. is called.
  2551. Arguments:
  2552. hFile - Specifies the communication device to be adjusted.
  2553. lpErrors - Points to the DWORD that is to receive the mask of the
  2554. error that occured.
  2555. lpStat - Points to the COMMSTAT structure that is to receive
  2556. the device status. The structure contains information
  2557. about the communications device.
  2558. Return Value:
  2559. The return value is TRUE if the function is successful or FALSE
  2560. if an error occurs.
  2561. --*/
  2562. {
  2563. NTSTATUS Status;
  2564. HANDLE SyncEvent;
  2565. IO_STATUS_BLOCK Iosb;
  2566. SERIAL_STATUS LocalStat;
  2567. RtlZeroMemory(&LocalStat, sizeof(SERIAL_STATUS));
  2568. if (!(SyncEvent = CreateEvent(
  2569. NULL,
  2570. TRUE,
  2571. FALSE,
  2572. NULL
  2573. ))) {
  2574. return FALSE;
  2575. }
  2576. Status = NtDeviceIoControlFile(
  2577. hFile,
  2578. SyncEvent,
  2579. NULL,
  2580. NULL,
  2581. &Iosb,
  2582. IOCTL_SERIAL_GET_COMMSTATUS,
  2583. NULL,
  2584. 0,
  2585. &LocalStat,
  2586. sizeof(LocalStat)
  2587. );
  2588. if ( Status == STATUS_PENDING) {
  2589. // Operation must complete before return & IoStatusBlock destroyed
  2590. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  2591. if ( NT_SUCCESS(Status)) {
  2592. Status = Iosb.Status;
  2593. }
  2594. }
  2595. if (NT_ERROR(Status)) {
  2596. CloseHandle(SyncEvent);
  2597. BaseSetLastNTError(Status);
  2598. return FALSE;
  2599. }
  2600. if (lpStat) {
  2601. //
  2602. // All is well up to this point. Translate the NT values
  2603. // into win32 values.
  2604. //
  2605. if (LocalStat.HoldReasons & SERIAL_TX_WAITING_FOR_CTS) {
  2606. lpStat->fCtsHold = TRUE;
  2607. } else {
  2608. lpStat->fCtsHold = FALSE;
  2609. }
  2610. if (LocalStat.HoldReasons & SERIAL_TX_WAITING_FOR_DSR) {
  2611. lpStat->fDsrHold = TRUE;
  2612. } else {
  2613. lpStat->fDsrHold = FALSE;
  2614. }
  2615. if (LocalStat.HoldReasons & SERIAL_TX_WAITING_FOR_DCD) {
  2616. lpStat->fRlsdHold = TRUE;
  2617. } else {
  2618. lpStat->fRlsdHold = FALSE;
  2619. }
  2620. if (LocalStat.HoldReasons & SERIAL_TX_WAITING_FOR_XON) {
  2621. lpStat->fXoffHold = TRUE;
  2622. } else {
  2623. lpStat->fXoffHold = FALSE;
  2624. }
  2625. if (LocalStat.HoldReasons & SERIAL_TX_WAITING_XOFF_SENT) {
  2626. lpStat->fXoffSent = TRUE;
  2627. } else {
  2628. lpStat->fXoffSent = FALSE;
  2629. }
  2630. lpStat->fEof = LocalStat.EofReceived;
  2631. lpStat->fTxim = LocalStat.WaitForImmediate;
  2632. lpStat->cbInQue = LocalStat.AmountInInQueue;
  2633. lpStat->cbOutQue = LocalStat.AmountInOutQueue;
  2634. }
  2635. if (lpErrors) {
  2636. *lpErrors = 0;
  2637. if (LocalStat.Errors & SERIAL_ERROR_BREAK) {
  2638. *lpErrors = *lpErrors | CE_BREAK;
  2639. }
  2640. if (LocalStat.Errors & SERIAL_ERROR_FRAMING) {
  2641. *lpErrors = *lpErrors | CE_FRAME;
  2642. }
  2643. if (LocalStat.Errors & SERIAL_ERROR_OVERRUN) {
  2644. *lpErrors = *lpErrors | CE_OVERRUN;
  2645. }
  2646. if (LocalStat.Errors & SERIAL_ERROR_QUEUEOVERRUN) {
  2647. *lpErrors = *lpErrors | CE_RXOVER;
  2648. }
  2649. if (LocalStat.Errors & SERIAL_ERROR_PARITY) {
  2650. *lpErrors = *lpErrors | CE_RXPARITY;
  2651. }
  2652. }
  2653. CloseHandle(SyncEvent);
  2654. return TRUE;
  2655. }
  2656. BOOL
  2657. SetupComm(
  2658. HANDLE hFile,
  2659. DWORD dwInQueue,
  2660. DWORD dwOutQueue
  2661. )
  2662. /*++
  2663. Routine Description:
  2664. The communication device is not initialized until SetupComm is
  2665. called. This function allocates space for receive and transmit
  2666. queues. These queues are used by the interrupt-driven transmit/
  2667. receive software and are internal to the provider.
  2668. Arguments:
  2669. hFile - Specifies the communication device to receive the settings.
  2670. The CreateFile function returns this value.
  2671. dwInQueue - Specifies the recommended size of the provider's
  2672. internal receive queue in bytes. This value must be
  2673. even. A value of -1 indicates that the default should
  2674. be used.
  2675. dwOutQueue - Specifies the recommended size of the provider's
  2676. internal transmit queue in bytes. This value must be
  2677. even. A value of -1 indicates that the default should
  2678. be used.
  2679. Return Value:
  2680. The return value is TRUE if the function is successful or FALSE
  2681. if an error occurs.
  2682. --*/
  2683. {
  2684. NTSTATUS Status;
  2685. HANDLE SyncEvent;
  2686. IO_STATUS_BLOCK Iosb;
  2687. SERIAL_QUEUE_SIZE NewSizes = {0};
  2688. //
  2689. // Make sure that the sizes are even.
  2690. //
  2691. if (dwOutQueue != ((DWORD)-1)) {
  2692. if (((dwOutQueue/2)*2) != dwOutQueue) {
  2693. SetLastError(ERROR_INVALID_DATA);
  2694. return FALSE;
  2695. }
  2696. }
  2697. if (dwInQueue != ((DWORD)-1)) {
  2698. if (((dwInQueue/2)*2) != dwInQueue) {
  2699. SetLastError(ERROR_INVALID_DATA);
  2700. return FALSE;
  2701. }
  2702. }
  2703. NewSizes.InSize = dwInQueue;
  2704. NewSizes.OutSize = dwOutQueue;
  2705. if (!(SyncEvent = CreateEvent(
  2706. NULL,
  2707. TRUE,
  2708. FALSE,
  2709. NULL
  2710. ))) {
  2711. return FALSE;
  2712. }
  2713. Status = NtDeviceIoControlFile(
  2714. hFile,
  2715. SyncEvent,
  2716. NULL,
  2717. NULL,
  2718. &Iosb,
  2719. IOCTL_SERIAL_SET_QUEUE_SIZE,
  2720. &NewSizes,
  2721. sizeof(SERIAL_QUEUE_SIZE),
  2722. NULL,
  2723. 0
  2724. );
  2725. if ( Status == STATUS_PENDING) {
  2726. // Operation must complete before return & IoStatusBlock destroyed
  2727. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  2728. if ( NT_SUCCESS(Status)) {
  2729. Status = Iosb.Status;
  2730. }
  2731. }
  2732. if (NT_ERROR(Status)) {
  2733. CloseHandle(SyncEvent);
  2734. BaseSetLastNTError(Status);
  2735. return FALSE;
  2736. }
  2737. CloseHandle(SyncEvent);
  2738. return TRUE;
  2739. }
  2740. BOOL
  2741. GetCommState(
  2742. HANDLE hFile,
  2743. LPDCB lpDCB
  2744. )
  2745. /*++
  2746. Routine Description:
  2747. This function fills the buffer pointed to by the lpDCB parameter with
  2748. the device control block of the communication device specified by hFile
  2749. parameter.
  2750. Arguments:
  2751. hFile - Specifies the communication device to be examined.
  2752. The CreateFile function returns this value.
  2753. lpDCB - Points to the DCB data structure that is to receive the current
  2754. device control block. The structure defines the control settings
  2755. for the device.
  2756. Return Value:
  2757. The return value is TRUE if the function is successful or FALSE
  2758. if an error occurs.
  2759. --*/
  2760. {
  2761. SERIAL_BAUD_RATE LocalBaud;
  2762. SERIAL_LINE_CONTROL LineControl;
  2763. SERIAL_CHARS Chars;
  2764. SERIAL_HANDFLOW HandFlow;
  2765. IO_STATUS_BLOCK Iosb;
  2766. NTSTATUS Status;
  2767. //
  2768. // Given the possiblity that the app may be doing asynchronous
  2769. // io we need an event to wait on.
  2770. //
  2771. // We need to make sure that any exit to this routine closes this
  2772. // event handle.
  2773. //
  2774. HANDLE SyncEvent;
  2775. //
  2776. // Make sure the windows mapping is the same as the NT mapping.
  2777. //
  2778. ASSERT((ONESTOPBIT == STOP_BIT_1) &&
  2779. (ONE5STOPBITS == STOP_BITS_1_5) &&
  2780. (TWOSTOPBITS == STOP_BITS_2));
  2781. ASSERT((NOPARITY == NO_PARITY) &&
  2782. (ODDPARITY == ODD_PARITY) &&
  2783. (EVENPARITY == EVEN_PARITY) &&
  2784. (MARKPARITY == MARK_PARITY) &&
  2785. (SPACEPARITY == SPACE_PARITY));
  2786. //
  2787. // Zero out the dcb. This might create an access violation
  2788. // if it isn't big enough. Which is ok, since we would rather
  2789. // get it before we create the sync event.
  2790. //
  2791. RtlZeroMemory(lpDCB, sizeof(DCB));
  2792. lpDCB->DCBlength = sizeof(DCB);
  2793. lpDCB->fBinary = TRUE;
  2794. if (!(SyncEvent = CreateEvent(
  2795. NULL,
  2796. TRUE,
  2797. FALSE,
  2798. NULL
  2799. ))) {
  2800. return FALSE;
  2801. }
  2802. Status = NtDeviceIoControlFile(
  2803. hFile,
  2804. SyncEvent,
  2805. NULL,
  2806. NULL,
  2807. &Iosb,
  2808. IOCTL_SERIAL_GET_BAUD_RATE,
  2809. NULL,
  2810. 0,
  2811. &LocalBaud,
  2812. sizeof(LocalBaud)
  2813. );
  2814. if ( Status == STATUS_PENDING) {
  2815. // Operation must complete before return & IoStatusBlock destroyed
  2816. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  2817. if ( NT_SUCCESS(Status)) {
  2818. Status = Iosb.Status;
  2819. }
  2820. }
  2821. if (NT_ERROR(Status)) {
  2822. CloseHandle(SyncEvent);
  2823. BaseSetLastNTError(Status);
  2824. return FALSE;
  2825. }
  2826. lpDCB->BaudRate = LocalBaud.BaudRate;
  2827. Status = NtDeviceIoControlFile(
  2828. hFile,
  2829. SyncEvent,
  2830. NULL,
  2831. NULL,
  2832. &Iosb,
  2833. IOCTL_SERIAL_GET_LINE_CONTROL,
  2834. NULL,
  2835. 0,
  2836. &LineControl,
  2837. sizeof(LineControl)
  2838. );
  2839. if ( Status == STATUS_PENDING) {
  2840. // Operation must complete before return & IoStatusBlock destroyed
  2841. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  2842. if ( NT_SUCCESS(Status)) {
  2843. Status = Iosb.Status;
  2844. }
  2845. }
  2846. if (NT_ERROR(Status)) {
  2847. CloseHandle(SyncEvent);
  2848. BaseSetLastNTError(Status);
  2849. return FALSE;
  2850. }
  2851. lpDCB->Parity = LineControl.Parity;
  2852. lpDCB->ByteSize = LineControl.WordLength;
  2853. lpDCB->StopBits = LineControl.StopBits;
  2854. Status = NtDeviceIoControlFile(
  2855. hFile,
  2856. SyncEvent,
  2857. NULL,
  2858. NULL,
  2859. &Iosb,
  2860. IOCTL_SERIAL_GET_CHARS,
  2861. NULL,
  2862. 0,
  2863. &Chars,
  2864. sizeof(Chars)
  2865. );
  2866. if ( Status == STATUS_PENDING) {
  2867. // Operation must complete before return & IoStatusBlock destroyed
  2868. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  2869. if ( NT_SUCCESS(Status)) {
  2870. Status = Iosb.Status;
  2871. }
  2872. }
  2873. if (NT_ERROR(Status)) {
  2874. CloseHandle(SyncEvent);
  2875. BaseSetLastNTError(Status);
  2876. return FALSE;
  2877. }
  2878. lpDCB->XonChar = Chars.XonChar;
  2879. lpDCB->XoffChar = Chars.XoffChar;
  2880. lpDCB->ErrorChar = Chars.ErrorChar;
  2881. lpDCB->EofChar = Chars.EofChar;
  2882. lpDCB->EvtChar = Chars.EventChar;
  2883. Status = NtDeviceIoControlFile(
  2884. hFile,
  2885. SyncEvent,
  2886. NULL,
  2887. NULL,
  2888. &Iosb,
  2889. IOCTL_SERIAL_GET_HANDFLOW,
  2890. NULL,
  2891. 0,
  2892. &HandFlow,
  2893. sizeof(HandFlow)
  2894. );
  2895. if ( Status == STATUS_PENDING) {
  2896. // Operation must complete before return & IoStatusBlock destroyed
  2897. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  2898. if ( NT_SUCCESS(Status)) {
  2899. Status = Iosb.Status;
  2900. }
  2901. }
  2902. if (NT_ERROR(Status)) {
  2903. CloseHandle(SyncEvent);
  2904. BaseSetLastNTError(Status);
  2905. return FALSE;
  2906. }
  2907. if (HandFlow.ControlHandShake & SERIAL_CTS_HANDSHAKE) {
  2908. lpDCB->fOutxCtsFlow = TRUE;
  2909. }
  2910. if (HandFlow.ControlHandShake & SERIAL_DSR_HANDSHAKE) {
  2911. lpDCB->fOutxDsrFlow = TRUE;
  2912. }
  2913. if (HandFlow.FlowReplace & SERIAL_AUTO_TRANSMIT) {
  2914. lpDCB->fOutX = TRUE;
  2915. }
  2916. if (HandFlow.FlowReplace & SERIAL_AUTO_RECEIVE) {
  2917. lpDCB->fInX = TRUE;
  2918. }
  2919. if (HandFlow.FlowReplace & SERIAL_NULL_STRIPPING) {
  2920. lpDCB->fNull = TRUE;
  2921. }
  2922. if (HandFlow.FlowReplace & SERIAL_ERROR_CHAR) {
  2923. lpDCB->fErrorChar = TRUE;
  2924. }
  2925. if (HandFlow.FlowReplace & SERIAL_XOFF_CONTINUE) {
  2926. lpDCB->fTXContinueOnXoff = TRUE;
  2927. }
  2928. if (HandFlow.ControlHandShake & SERIAL_ERROR_ABORT) {
  2929. lpDCB->fAbortOnError = TRUE;
  2930. }
  2931. switch (HandFlow.FlowReplace & SERIAL_RTS_MASK) {
  2932. case 0:
  2933. lpDCB->fRtsControl = RTS_CONTROL_DISABLE;
  2934. break;
  2935. case SERIAL_RTS_CONTROL:
  2936. lpDCB->fRtsControl = RTS_CONTROL_ENABLE;
  2937. break;
  2938. case SERIAL_RTS_HANDSHAKE:
  2939. lpDCB->fRtsControl = RTS_CONTROL_HANDSHAKE;
  2940. break;
  2941. case SERIAL_TRANSMIT_TOGGLE:
  2942. lpDCB->fRtsControl = RTS_CONTROL_TOGGLE;
  2943. break;
  2944. }
  2945. switch (HandFlow.ControlHandShake & SERIAL_DTR_MASK) {
  2946. case 0:
  2947. lpDCB->fDtrControl = DTR_CONTROL_DISABLE;
  2948. break;
  2949. case SERIAL_DTR_CONTROL:
  2950. lpDCB->fDtrControl = DTR_CONTROL_ENABLE;
  2951. break;
  2952. case SERIAL_DTR_HANDSHAKE:
  2953. lpDCB->fDtrControl = DTR_CONTROL_HANDSHAKE;
  2954. break;
  2955. }
  2956. lpDCB->fDsrSensitivity =
  2957. (HandFlow.ControlHandShake & SERIAL_DSR_SENSITIVITY)?(TRUE):(FALSE);
  2958. lpDCB->XonLim = (WORD)HandFlow.XonLimit;
  2959. lpDCB->XoffLim = (WORD)HandFlow.XoffLimit;
  2960. CloseHandle(SyncEvent);
  2961. return TRUE;
  2962. }
  2963. BOOL
  2964. EscapeCommFunction(
  2965. HANDLE hFile,
  2966. DWORD dwFunc
  2967. )
  2968. /*++
  2969. Routine Description:
  2970. This function directs the communication-device specified by the
  2971. hFile parameter to carry out the extended function specified by
  2972. the dwFunc parameter.
  2973. Arguments:
  2974. hFile - Specifies the communication device to receive the settings.
  2975. The CreateFile function returns this value.
  2976. dwFunc - Specifies the function code of the extended function.
  2977. Return Value:
  2978. The return value is TRUE if the function is successful or FALSE
  2979. if an error occurs.
  2980. --*/
  2981. {
  2982. NTSTATUS Status;
  2983. IO_STATUS_BLOCK Iosb;
  2984. ULONG ControlCode;
  2985. HANDLE Event;
  2986. switch (dwFunc) {
  2987. case SETXOFF: {
  2988. ControlCode = IOCTL_SERIAL_SET_XOFF;
  2989. break;
  2990. }
  2991. case SETXON: {
  2992. ControlCode = IOCTL_SERIAL_SET_XON;
  2993. break;
  2994. }
  2995. case SETRTS: {
  2996. ControlCode = IOCTL_SERIAL_SET_RTS;
  2997. break;
  2998. }
  2999. case CLRRTS: {
  3000. ControlCode = IOCTL_SERIAL_CLR_RTS;
  3001. break;
  3002. }
  3003. case SETDTR: {
  3004. ControlCode = IOCTL_SERIAL_SET_DTR;
  3005. break;
  3006. }
  3007. case CLRDTR: {
  3008. ControlCode = IOCTL_SERIAL_CLR_DTR;
  3009. break;
  3010. }
  3011. case RESETDEV: {
  3012. ControlCode = IOCTL_SERIAL_RESET_DEVICE;
  3013. break;
  3014. }
  3015. case SETBREAK: {
  3016. ControlCode = IOCTL_SERIAL_SET_BREAK_ON;
  3017. break;
  3018. }
  3019. case CLRBREAK: {
  3020. ControlCode = IOCTL_SERIAL_SET_BREAK_OFF;
  3021. break;
  3022. }
  3023. default: {
  3024. SetLastError(ERROR_INVALID_PARAMETER);
  3025. return FALSE;
  3026. }
  3027. }
  3028. if (!(Event = CreateEvent(
  3029. NULL,
  3030. TRUE,
  3031. FALSE,
  3032. NULL
  3033. ))) {
  3034. return FALSE;
  3035. }
  3036. Status = NtDeviceIoControlFile(
  3037. hFile,
  3038. Event,
  3039. NULL,
  3040. NULL,
  3041. &Iosb,
  3042. ControlCode,
  3043. NULL,
  3044. 0,
  3045. NULL,
  3046. 0
  3047. );
  3048. if ( Status == STATUS_PENDING) {
  3049. // Operation must complete before return & IoStatusBlock destroyed
  3050. Status = NtWaitForSingleObject( Event, FALSE, NULL );
  3051. if ( NT_SUCCESS(Status)) {
  3052. Status = Iosb.Status;
  3053. }
  3054. }
  3055. if (NT_ERROR(Status)) {
  3056. CloseHandle(Event);
  3057. BaseSetLastNTError(Status);
  3058. return FALSE;
  3059. }
  3060. CloseHandle(Event);
  3061. return TRUE;
  3062. }
  3063. BOOL
  3064. SetCommState(
  3065. HANDLE hFile,
  3066. LPDCB lpDCB
  3067. )
  3068. /*++
  3069. Routine Description:
  3070. The SetCommState function sets a communication device to the state
  3071. specified in the lpDCB parameter. The device is identified by the
  3072. hFile parameter. This function reinitializes all hardwae and controls
  3073. as specified byt the lpDCB, but does not empty the transmit or
  3074. receive queues.
  3075. Arguments:
  3076. hFile - Specifies the communication device to receive the settings.
  3077. The CreateFile function returns this value.
  3078. lpDCB - Points to a DCB structure that contains the desired
  3079. communications setting for the device.
  3080. Return Value:
  3081. The return value is TRUE if the function is successful or FALSE
  3082. if an error occurs.
  3083. --*/
  3084. {
  3085. SERIAL_BAUD_RATE LocalBaud;
  3086. SERIAL_LINE_CONTROL LineControl;
  3087. SERIAL_CHARS Chars;
  3088. SERIAL_HANDFLOW HandFlow = {0};
  3089. IO_STATUS_BLOCK Iosb;
  3090. NTSTATUS Status;
  3091. //
  3092. // Keep a copy of what the DCB was like before we started
  3093. // changing things. If some error occurs we can use
  3094. // it to restore the old setup.
  3095. //
  3096. DCB OldDcb;
  3097. //
  3098. // Given the possiblity that the app may be doing asynchronous
  3099. // io we need an event to wait on. While it would be very
  3100. // strange to be setting the comm state while IO is active
  3101. // we need to make sure we don't compound the problem by
  3102. // returning before this API's IO is actually finished. This
  3103. // can happen because the file handle is set on the completion
  3104. // of any IO.
  3105. //
  3106. // We need to make sure that any exit to this routine closes this
  3107. // event handle.
  3108. //
  3109. HANDLE SyncEvent;
  3110. if (GetCommState(
  3111. hFile,
  3112. &OldDcb
  3113. )) {
  3114. //
  3115. // Try to set the baud rate. If we fail here, we just return
  3116. // because we never actually got to set anything.
  3117. //
  3118. if (!(SyncEvent = CreateEvent(
  3119. NULL,
  3120. TRUE,
  3121. FALSE,
  3122. NULL
  3123. ))) {
  3124. return FALSE;
  3125. }
  3126. LocalBaud.BaudRate = lpDCB->BaudRate;
  3127. Status = NtDeviceIoControlFile(
  3128. hFile,
  3129. SyncEvent,
  3130. NULL,
  3131. NULL,
  3132. &Iosb,
  3133. IOCTL_SERIAL_SET_BAUD_RATE,
  3134. &LocalBaud,
  3135. sizeof(LocalBaud),
  3136. NULL,
  3137. 0
  3138. );
  3139. if ( Status == STATUS_PENDING) {
  3140. // Operation must complete before return & IoStatusBlock destroyed
  3141. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  3142. if ( NT_SUCCESS(Status)) {
  3143. Status = Iosb.Status;
  3144. }
  3145. }
  3146. if (NT_ERROR(Status)) {
  3147. CloseHandle(SyncEvent);
  3148. BaseSetLastNTError(Status);
  3149. return FALSE;
  3150. }
  3151. LineControl.StopBits = lpDCB->StopBits;
  3152. LineControl.Parity = lpDCB->Parity;
  3153. LineControl.WordLength = lpDCB->ByteSize;
  3154. LocalBaud.BaudRate = lpDCB->BaudRate;
  3155. Chars.XonChar = lpDCB->XonChar;
  3156. Chars.XoffChar = lpDCB->XoffChar;
  3157. Chars.ErrorChar = lpDCB->ErrorChar;
  3158. Chars.BreakChar = lpDCB->ErrorChar;
  3159. Chars.EofChar = lpDCB->EofChar;
  3160. Chars.EventChar = lpDCB->EvtChar;
  3161. HandFlow.FlowReplace &= ~SERIAL_RTS_MASK;
  3162. switch (lpDCB->fRtsControl) {
  3163. case RTS_CONTROL_DISABLE:
  3164. break;
  3165. case RTS_CONTROL_ENABLE:
  3166. HandFlow.FlowReplace |= SERIAL_RTS_CONTROL;
  3167. break;
  3168. case RTS_CONTROL_HANDSHAKE:
  3169. HandFlow.FlowReplace |= SERIAL_RTS_HANDSHAKE;
  3170. break;
  3171. case RTS_CONTROL_TOGGLE:
  3172. HandFlow.FlowReplace |= SERIAL_TRANSMIT_TOGGLE;
  3173. break;
  3174. default:
  3175. SetCommState(
  3176. hFile,
  3177. &OldDcb
  3178. );
  3179. CloseHandle(SyncEvent);
  3180. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  3181. return FALSE;
  3182. }
  3183. HandFlow.ControlHandShake &= ~SERIAL_DTR_MASK;
  3184. switch (lpDCB->fDtrControl) {
  3185. case DTR_CONTROL_DISABLE:
  3186. break;
  3187. case DTR_CONTROL_ENABLE:
  3188. HandFlow.ControlHandShake |= SERIAL_DTR_CONTROL;
  3189. break;
  3190. case DTR_CONTROL_HANDSHAKE:
  3191. HandFlow.ControlHandShake |= SERIAL_DTR_HANDSHAKE;
  3192. break;
  3193. default:
  3194. SetCommState(
  3195. hFile,
  3196. &OldDcb
  3197. );
  3198. CloseHandle(SyncEvent);
  3199. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  3200. return FALSE;
  3201. }
  3202. if (lpDCB->fDsrSensitivity) {
  3203. HandFlow.ControlHandShake |= SERIAL_DSR_SENSITIVITY;
  3204. }
  3205. if (lpDCB->fOutxCtsFlow) {
  3206. HandFlow.ControlHandShake |= SERIAL_CTS_HANDSHAKE;
  3207. }
  3208. if (lpDCB->fOutxDsrFlow) {
  3209. HandFlow.ControlHandShake |= SERIAL_DSR_HANDSHAKE;
  3210. }
  3211. if (lpDCB->fOutX) {
  3212. HandFlow.FlowReplace |= SERIAL_AUTO_TRANSMIT;
  3213. }
  3214. if (lpDCB->fInX) {
  3215. HandFlow.FlowReplace |= SERIAL_AUTO_RECEIVE;
  3216. }
  3217. if (lpDCB->fNull) {
  3218. HandFlow.FlowReplace |= SERIAL_NULL_STRIPPING;
  3219. }
  3220. if (lpDCB->fErrorChar) {
  3221. HandFlow.FlowReplace |= SERIAL_ERROR_CHAR;
  3222. }
  3223. if (lpDCB->fTXContinueOnXoff) {
  3224. HandFlow.FlowReplace |= SERIAL_XOFF_CONTINUE;
  3225. }
  3226. if (lpDCB->fAbortOnError) {
  3227. HandFlow.ControlHandShake |= SERIAL_ERROR_ABORT;
  3228. }
  3229. //
  3230. // For win95 compatiblity, if we are setting with
  3231. // xxx_control_XXXXXXX then set the modem status line
  3232. // to that state.
  3233. //
  3234. if (lpDCB->fRtsControl == RTS_CONTROL_ENABLE) {
  3235. EscapeCommFunction(
  3236. hFile,
  3237. SETRTS
  3238. );
  3239. } else if (lpDCB->fRtsControl == RTS_CONTROL_DISABLE) {
  3240. EscapeCommFunction(
  3241. hFile,
  3242. CLRRTS
  3243. );
  3244. }
  3245. if (lpDCB->fDtrControl == DTR_CONTROL_ENABLE) {
  3246. EscapeCommFunction(
  3247. hFile,
  3248. SETDTR
  3249. );
  3250. } else if (lpDCB->fDtrControl == DTR_CONTROL_DISABLE) {
  3251. EscapeCommFunction(
  3252. hFile,
  3253. CLRDTR
  3254. );
  3255. }
  3256. HandFlow.XonLimit = lpDCB->XonLim;
  3257. HandFlow.XoffLimit = lpDCB->XoffLim;
  3258. Status = NtDeviceIoControlFile(
  3259. hFile,
  3260. SyncEvent,
  3261. NULL,
  3262. NULL,
  3263. &Iosb,
  3264. IOCTL_SERIAL_SET_LINE_CONTROL,
  3265. &LineControl,
  3266. sizeof(LineControl),
  3267. NULL,
  3268. 0
  3269. );
  3270. if ( Status == STATUS_PENDING) {
  3271. // Operation must complete before return & IoStatusBlock destroyed
  3272. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  3273. if ( NT_SUCCESS(Status)) {
  3274. Status = Iosb.Status;
  3275. }
  3276. }
  3277. if (NT_ERROR(Status)) {
  3278. CloseHandle(SyncEvent);
  3279. SetCommState(
  3280. hFile,
  3281. &OldDcb
  3282. );
  3283. BaseSetLastNTError(Status);
  3284. return FALSE;
  3285. }
  3286. Status = NtDeviceIoControlFile(
  3287. hFile,
  3288. SyncEvent,
  3289. NULL,
  3290. NULL,
  3291. &Iosb,
  3292. IOCTL_SERIAL_SET_CHARS,
  3293. &Chars,
  3294. sizeof(Chars),
  3295. NULL,
  3296. 0
  3297. );
  3298. if ( Status == STATUS_PENDING) {
  3299. // Operation must complete before return & IoStatusBlock destroyed
  3300. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  3301. if ( NT_SUCCESS(Status)) {
  3302. Status = Iosb.Status;
  3303. }
  3304. }
  3305. if (NT_ERROR(Status)) {
  3306. CloseHandle(SyncEvent);
  3307. SetCommState(
  3308. hFile,
  3309. &OldDcb
  3310. );
  3311. BaseSetLastNTError(Status);
  3312. return FALSE;
  3313. }
  3314. Status = NtDeviceIoControlFile(
  3315. hFile,
  3316. SyncEvent,
  3317. NULL,
  3318. NULL,
  3319. &Iosb,
  3320. IOCTL_SERIAL_SET_HANDFLOW,
  3321. &HandFlow,
  3322. sizeof(HandFlow),
  3323. NULL,
  3324. 0
  3325. );
  3326. if ( Status == STATUS_PENDING) {
  3327. // Operation must complete before return & IoStatusBlock destroyed
  3328. Status = NtWaitForSingleObject( SyncEvent, FALSE, NULL );
  3329. if ( NT_SUCCESS(Status)) {
  3330. Status = Iosb.Status;
  3331. }
  3332. }
  3333. if (NT_ERROR(Status)) {
  3334. CloseHandle(SyncEvent);
  3335. SetCommState(
  3336. hFile,
  3337. &OldDcb
  3338. );
  3339. BaseSetLastNTError(Status);
  3340. return FALSE;
  3341. }
  3342. CloseHandle(SyncEvent);
  3343. return TRUE;
  3344. }
  3345. return FALSE;
  3346. }
  3347. BOOL
  3348. SetCommTimeouts(
  3349. HANDLE hFile,
  3350. LPCOMMTIMEOUTS lpCommTimeouts
  3351. )
  3352. /*++
  3353. Routine Description:
  3354. This function establishes the timeout characteristics for all
  3355. read and write operations on the handle specified by hFile.
  3356. Arguments:
  3357. hFile - Specifies the communication device to receive the settings.
  3358. The CreateFile function returns this value.
  3359. lpCommTimeouts - Points to a structure containing timeout parameters.
  3360. Return Value:
  3361. The return value is TRUE if the function is successful or FALSE
  3362. if an error occurs.
  3363. --*/
  3364. {
  3365. SERIAL_TIMEOUTS To;
  3366. NTSTATUS Status;
  3367. IO_STATUS_BLOCK Iosb;
  3368. HANDLE Event;
  3369. To.ReadIntervalTimeout = lpCommTimeouts->ReadIntervalTimeout;
  3370. To.ReadTotalTimeoutMultiplier = lpCommTimeouts->ReadTotalTimeoutMultiplier;
  3371. To.ReadTotalTimeoutConstant = lpCommTimeouts->ReadTotalTimeoutConstant;
  3372. To.WriteTotalTimeoutMultiplier = lpCommTimeouts->WriteTotalTimeoutMultiplier;
  3373. To.WriteTotalTimeoutConstant = lpCommTimeouts->WriteTotalTimeoutConstant;
  3374. if (!(Event = CreateEvent(
  3375. NULL,
  3376. TRUE,
  3377. FALSE,
  3378. NULL
  3379. ))) {
  3380. return FALSE;
  3381. } else {
  3382. Status = NtDeviceIoControlFile(
  3383. hFile,
  3384. Event,
  3385. NULL,
  3386. NULL,
  3387. &Iosb,
  3388. IOCTL_SERIAL_SET_TIMEOUTS,
  3389. &To,
  3390. sizeof(To),
  3391. NULL,
  3392. 0
  3393. );
  3394. if ( Status == STATUS_PENDING) {
  3395. // Operation must complete before return & IoStatusBlock destroyed
  3396. Status = NtWaitForSingleObject( Event, FALSE, NULL );
  3397. if ( NT_SUCCESS(Status)) {
  3398. Status = Iosb.Status;
  3399. }
  3400. }
  3401. if (NT_ERROR(Status)) {
  3402. CloseHandle(Event);
  3403. BaseSetLastNTError(Status);
  3404. return FALSE;
  3405. }
  3406. CloseHandle(Event);
  3407. return TRUE;
  3408. }
  3409. }
  3410. BOOL
  3411. APIENTRY
  3412. InitializeSecurityDescriptor (
  3413. PSECURITY_DESCRIPTOR pSecurityDescriptor,
  3414. DWORD dwRevision
  3415. )
  3416. {
  3417. NTSTATUS Status;
  3418. Status = RtlCreateSecurityDescriptor (
  3419. pSecurityDescriptor,
  3420. dwRevision
  3421. );
  3422. if ( !NT_SUCCESS(Status) ) {
  3423. BaseSetLastNTError(Status);
  3424. return FALSE;
  3425. }
  3426. return TRUE;
  3427. }
  3428. BOOL
  3429. APIENTRY
  3430. SetSecurityDescriptorDacl (
  3431. PSECURITY_DESCRIPTOR pSecurityDescriptor,
  3432. BOOL bDaclPresent,
  3433. PACL pDacl OPTIONAL,
  3434. BOOL bDaclDefaulted OPTIONAL
  3435. )
  3436. {
  3437. NTSTATUS Status;
  3438. Status = RtlSetDaclSecurityDescriptor (
  3439. pSecurityDescriptor,
  3440. (BOOLEAN)bDaclPresent,
  3441. pDacl,
  3442. (BOOLEAN)bDaclDefaulted
  3443. );
  3444. if ( !NT_SUCCESS(Status) ) {
  3445. BaseSetLastNTError(Status);
  3446. return FALSE;
  3447. }
  3448. return TRUE;
  3449. }
  3450. ULONG
  3451. APIENTRY
  3452. GetTickCount(void)
  3453. {
  3454. return NtGetTickCount();
  3455. }
  3456. #endif // #ifdef NT_NATIVE