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

5081 lines
161 KiB

  1. /*++
  2. Copyright (c) Corporation
  3. Module Name:
  4. trcapi.c
  5. Abstract:
  6. This module contains implementations of win32 api's used in wmi files.
  7. Author:
  8. Revision History:
  9. --*/
  10. #include <nt.h>
  11. #include "nls.h"
  12. #include "wmiump.h"
  13. #include "trcapi.h"
  14. #include <strsafe.h>
  15. ULONG BaseDllTag;
  16. #define TLS_MASK 0x80000000
  17. #define TMP_TAG 0
  18. #if defined(_WIN64) || defined(BUILD_WOW6432)
  19. SYSTEM_BASIC_INFORMATION SysInfo;
  20. #define BASE_SYSINFO (SysInfo)
  21. #else
  22. #define BASE_SYSINFO (BaseStaticServerData->SysInfo)
  23. #endif
  24. #if defined(BUILD_WOW6432)
  25. #define UStr64ToUStr(dst, src) ( (dst)->Length = (src)->Length, \
  26. (dst)->MaximumLength = (src)->MaximumLength, \
  27. (dst)->Buffer = (PWSTR) ((src)->Buffer), \
  28. (dst) \
  29. )
  30. // In the 32BIT kernel32, on NT64 multiple the index by 2 since pointer
  31. // are twice are large.
  32. #define BASE_SHARED_SERVER_DATA (NtCurrentPeb()->ReadOnlyStaticServerData[BASESRV_SERVERDLL_INDEX*2])
  33. #define BASE_SERVER_STR_TO_LOCAL_STR(d,s) UStr64ToUStr(d,s)
  34. #else
  35. #define BASE_SHARED_SERVER_DATA (NtCurrentPeb()->ReadOnlyStaticServerData[BASESRV_SERVERDLL_INDEX])
  36. #define BASE_SERVER_STR_TO_LOCAL_STR(d,s) *(d)=*(s)
  37. #endif
  38. DWORD
  39. WINAPI
  40. EtwpGetTimeZoneInformation(
  41. LPTIME_ZONE_INFORMATION lpTimeZoneInformation
  42. )
  43. /*++
  44. Routine Description:
  45. This function allows an application to get the current timezone
  46. parameters These parameters control the Universal time to Local time
  47. translations.
  48. All UTC time to Local time translations are based on the following
  49. formula:
  50. UTC = LocalTime + Bias
  51. The return value of this function is the systems best guess of
  52. the current time zone parameters. This is one of:
  53. - Unknown
  54. - Standard Time
  55. - Daylight Savings Time
  56. If SetTimeZoneInformation was called without the transition date
  57. information, Unknown is returned, but the currect bias is used for
  58. local time translation. Otherwise, the system will correctly pick
  59. either daylight savings time or standard time.
  60. The information returned by this API is identical to the information
  61. stored in the last successful call to SetTimeZoneInformation. The
  62. exception is the Bias field returns the current Bias value in
  63. Arguments:
  64. lpTimeZoneInformation - Supplies the address of the time zone
  65. information structure.
  66. Return Value:
  67. TIME_ZONE_ID_UNKNOWN - The system can not determine the current
  68. timezone. This is usually due to a previous call to
  69. SetTimeZoneInformation where only the Bias was supplied and no
  70. transition dates were supplied.
  71. TIME_ZONE_ID_STANDARD - The system is operating in the range covered
  72. by StandardDate.
  73. TIME_ZONE_ID_DAYLIGHT - The system is operating in the range covered
  74. by DaylightDate.
  75. 0xffffffff - The operation failed. Extended error status is
  76. available using EtwpGetLastError.
  77. --*/
  78. {
  79. RTL_TIME_ZONE_INFORMATION tzi;
  80. NTSTATUS Status;
  81. //
  82. // get the timezone data from the system
  83. // If it's terminal server session use client time zone
  84. Status = NtQuerySystemInformation(
  85. SystemCurrentTimeZoneInformation,
  86. &tzi,
  87. sizeof(tzi),
  88. NULL
  89. );
  90. if ( !NT_SUCCESS(Status) ) {
  91. EtwpBaseSetLastNTError(Status);
  92. return 0xffffffff;
  93. }
  94. lpTimeZoneInformation->Bias = tzi.Bias;
  95. lpTimeZoneInformation->StandardBias = tzi.StandardBias;
  96. lpTimeZoneInformation->DaylightBias = tzi.DaylightBias;
  97. RtlMoveMemory(&lpTimeZoneInformation->StandardName,&tzi.StandardName,sizeof(tzi.StandardName));
  98. RtlMoveMemory(&lpTimeZoneInformation->DaylightName,&tzi.DaylightName,sizeof(tzi.DaylightName));
  99. lpTimeZoneInformation->StandardDate.wYear = tzi.StandardStart.Year ;
  100. lpTimeZoneInformation->StandardDate.wMonth = tzi.StandardStart.Month ;
  101. lpTimeZoneInformation->StandardDate.wDayOfWeek = tzi.StandardStart.Weekday ;
  102. lpTimeZoneInformation->StandardDate.wDay = tzi.StandardStart.Day ;
  103. lpTimeZoneInformation->StandardDate.wHour = tzi.StandardStart.Hour ;
  104. lpTimeZoneInformation->StandardDate.wMinute = tzi.StandardStart.Minute ;
  105. lpTimeZoneInformation->StandardDate.wSecond = tzi.StandardStart.Second ;
  106. lpTimeZoneInformation->StandardDate.wMilliseconds = tzi.StandardStart.Milliseconds;
  107. lpTimeZoneInformation->DaylightDate.wYear = tzi.DaylightStart.Year ;
  108. lpTimeZoneInformation->DaylightDate.wMonth = tzi.DaylightStart.Month ;
  109. lpTimeZoneInformation->DaylightDate.wDayOfWeek = tzi.DaylightStart.Weekday ;
  110. lpTimeZoneInformation->DaylightDate.wDay = tzi.DaylightStart.Day ;
  111. lpTimeZoneInformation->DaylightDate.wHour = tzi.DaylightStart.Hour ;
  112. lpTimeZoneInformation->DaylightDate.wMinute = tzi.DaylightStart.Minute ;
  113. lpTimeZoneInformation->DaylightDate.wSecond = tzi.DaylightStart.Second ;
  114. lpTimeZoneInformation->DaylightDate.wMilliseconds = tzi.DaylightStart.Milliseconds;
  115. return USER_SHARED_DATA->TimeZoneId;
  116. }
  117. HANDLE
  118. WINAPI
  119. EtwpCreateFileW(
  120. LPCWSTR lpFileName,
  121. DWORD dwDesiredAccess,
  122. DWORD dwShareMode,
  123. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  124. DWORD dwCreationDisposition,
  125. DWORD dwFlagsAndAttributes,
  126. HANDLE hTemplateFile
  127. )
  128. /*++
  129. Routine Description:
  130. A file can be created, opened, or truncated, and a handle opened to
  131. access the new file using CreateFile.
  132. This API is used to create or open a file and obtain a handle to it
  133. that allows reading data, writing data, and moving the file pointer.
  134. This API allows the caller to specify the following creation
  135. dispositions:
  136. - Create a new file and fail if the file exists ( CREATE_NEW )
  137. - Create a new file and succeed if it exists ( CREATE_ALWAYS )
  138. - Open an existing file ( OPEN_EXISTING )
  139. - Open and existing file or create it if it does not exist (
  140. OPEN_ALWAYS )
  141. - Truncate and existing file ( TRUNCATE_EXISTING )
  142. If this call is successful, a handle is returned that has
  143. appropriate access to the specified file.
  144. If as a result of this call, a file is created,
  145. - The attributes of the file are determined by the value of the
  146. FileAttributes parameter or'd with the FILE_ATTRIBUTE_ARCHIVE bit.
  147. - The length of the file will be set to zero.
  148. - If the hTemplateFile parameter is specified, any extended
  149. attributes associated with the file are assigned to the new file.
  150. If a new file is not created, then the hTemplateFile is ignored as
  151. are any extended attributes.
  152. For DOS based systems running share.exe the file sharing semantics
  153. work as described above. Without share.exe no share level
  154. protection exists.
  155. This call is logically equivalent to DOS (int 21h, function 5Bh), or
  156. DOS (int 21h, function 3Ch) depending on the value of the
  157. FailIfExists parameter.
  158. Arguments:
  159. lpFileName - Supplies the file name of the file to open. Depending on
  160. the value of the FailIfExists parameter, this name may or may
  161. not already exist.
  162. dwDesiredAccess - Supplies the caller's desired access to the file.
  163. DesiredAccess Flags:
  164. GENERIC_READ - Read access to the file is requested. This
  165. allows data to be read from the file and the file pointer to
  166. be modified.
  167. GENERIC_WRITE - Write access to the file is requested. This
  168. allows data to be written to the file and the file pointer to
  169. be modified.
  170. dwShareMode - Supplies a set of flags that indicates how this file is
  171. to be shared with other openers of the file. A value of zero
  172. for this parameter indicates no sharing of the file, or
  173. exclusive access to the file is to occur.
  174. ShareMode Flags:
  175. FILE_SHARE_READ - Other open operations may be performed on the
  176. file for read access.
  177. FILE_SHARE_WRITE - Other open operations may be performed on the
  178. file for write access.
  179. lpSecurityAttributes - An optional parameter that, if present, and
  180. supported on the target file system supplies a security
  181. descriptor for the new file.
  182. dwCreationDisposition - Supplies a creation disposition that
  183. specifies how this call is to operate. This parameter must be
  184. one of the following values.
  185. dwCreationDisposition Value:
  186. CREATE_NEW - Create a new file. If the specified file already
  187. exists, then fail. The attributes for the new file are what
  188. is specified in the dwFlagsAndAttributes parameter or'd with
  189. FILE_ATTRIBUTE_ARCHIVE. If the hTemplateFile is specified,
  190. then any extended attributes associated with that file are
  191. propogated to the new file.
  192. CREATE_ALWAYS - Always create the file. If the file already
  193. exists, then it is overwritten. The attributes for the new
  194. file are what is specified in the dwFlagsAndAttributes
  195. parameter or'd with FILE_ATTRIBUTE_ARCHIVE. If the
  196. hTemplateFile is specified, then any extended attributes
  197. associated with that file are propogated to the new file.
  198. OPEN_EXISTING - Open the file, but if it does not exist, then
  199. fail the call.
  200. OPEN_ALWAYS - Open the file if it exists. If it does not exist,
  201. then create the file using the same rules as if the
  202. disposition were CREATE_NEW.
  203. TRUNCATE_EXISTING - Open the file, but if it does not exist,
  204. then fail the call. Once opened, the file is truncated such
  205. that its size is zero bytes. This disposition requires that
  206. the caller open the file with at least GENERIC_WRITE access.
  207. dwFlagsAndAttributes - Specifies flags and attributes for the file.
  208. The attributes are only used when the file is created (as
  209. opposed to opened or truncated). Any combination of attribute
  210. flags is acceptable except that all other attribute flags
  211. override the normal file attribute, FILE_ATTRIBUTE_NORMAL. The
  212. FILE_ATTRIBUTE_ARCHIVE flag is always implied.
  213. dwFlagsAndAttributes Flags:
  214. FILE_ATTRIBUTE_NORMAL - A normal file should be created.
  215. FILE_ATTRIBUTE_READONLY - A read-only file should be created.
  216. FILE_ATTRIBUTE_HIDDEN - A hidden file should be created.
  217. FILE_ATTRIBUTE_SYSTEM - A system file should be created.
  218. FILE_FLAG_WRITE_THROUGH - Indicates that the system should
  219. always write through any intermediate cache and go directly
  220. to the file. The system may still cache writes, but may not
  221. lazily flush the writes.
  222. FILE_FLAG_OVERLAPPED - Indicates that the system should initialize
  223. the file so that ReadFile and WriteFile operations that may
  224. take a significant time to complete will return ERROR_IO_PENDING.
  225. An event will be set to the signalled state when the operation
  226. completes. When FILE_FLAG_OVERLAPPED is specified the system will
  227. not maintain the file pointer. The position to read/write from
  228. is passed to the system as part of the OVERLAPPED structure
  229. which is an optional parameter to ReadFile and WriteFile.
  230. FILE_FLAG_NO_BUFFERING - Indicates that the file is to be opened
  231. with no intermediate buffering or caching done by the
  232. system. Reads and writes to the file must be done on sector
  233. boundries. Buffer addresses for reads and writes must be
  234. aligned on at least disk sector boundries in memory.
  235. FILE_FLAG_RANDOM_ACCESS - Indicates that access to the file may
  236. be random. The system cache manager may use this to influence
  237. its caching strategy for this file.
  238. FILE_FLAG_SEQUENTIAL_SCAN - Indicates that access to the file
  239. may be sequential. The system cache manager may use this to
  240. influence its caching strategy for this file. The file may
  241. in fact be accessed randomly, but the cache manager may
  242. optimize its cacheing policy for sequential access.
  243. FILE_FLAG_DELETE_ON_CLOSE - Indicates that the file is to be
  244. automatically deleted when the last handle to it is closed.
  245. FILE_FLAG_BACKUP_SEMANTICS - Indicates that the file is being opened
  246. or created for the purposes of either a backup or a restore
  247. operation. Thus, the system should make whatever checks are
  248. appropriate to ensure that the caller is able to override
  249. whatever security checks have been placed on the file to allow
  250. this to happen.
  251. FILE_FLAG_POSIX_SEMANTICS - Indicates that the file being opened
  252. should be accessed in a manner compatible with the rules used
  253. by POSIX. This includes allowing multiple files with the same
  254. name, differing only in case. WARNING: Use of this flag may
  255. render it impossible for a DOS, WIN-16, or WIN-32 application
  256. to access the file.
  257. FILE_FLAG_OPEN_REPARSE_POINT - Indicates that the file being opened
  258. should be accessed as if it were a reparse point. WARNING: Use
  259. of this flag may inhibit the operation of file system filter drivers
  260. present in the I/O subsystem.
  261. FILE_FLAG_OPEN_NO_RECALL - Indicates that all the state of the file
  262. should be acessed without changing its storage location. Thus,
  263. in the case of files that have parts of its state stored at a
  264. remote servicer, no permanent recall of data is to happen.
  265. Security Quality of Service information may also be specified in
  266. the dwFlagsAndAttributes parameter. These bits are meaningful
  267. only if the file being opened is the client side of a Named
  268. Pipe. Otherwise they are ignored.
  269. SECURITY_SQOS_PRESENT - Indicates that the Security Quality of
  270. Service bits contain valid values.
  271. Impersonation Levels:
  272. SECURITY_ANONYMOUS - Specifies that the client should be impersonated
  273. at Anonymous impersonation level.
  274. SECURITY_IDENTIFICAION - Specifies that the client should be impersonated
  275. at Identification impersonation level.
  276. SECURITY_IMPERSONATION - Specifies that the client should be impersonated
  277. at Impersonation impersonation level.
  278. SECURITY_DELEGATION - Specifies that the client should be impersonated
  279. at Delegation impersonation level.
  280. Context Tracking:
  281. SECURITY_CONTEXT_TRACKING - A boolean flag that when set,
  282. specifies that the Security Tracking Mode should be
  283. Dynamic, otherwise Static.
  284. SECURITY_EFFECTIVE_ONLY - A boolean flag indicating whether
  285. the entire security context of the client is to be made
  286. available to the server or only the effective aspects of
  287. the context.
  288. hTemplateFile - An optional parameter, then if specified, supplies a
  289. handle with GENERIC_READ access to a template file. The
  290. template file is used to supply extended attributes for the file
  291. being created. When the new file is created, the relevant attributes
  292. from the template file are used in creating the new file.
  293. Return Value:
  294. Not -1 - Returns an open handle to the specified file. Subsequent
  295. access to the file is controlled by the DesiredAccess parameter.
  296. 0xffffffff - The operation failed. Extended error status is available
  297. using EtwpGetLastError.
  298. --*/
  299. {
  300. NTSTATUS Status;
  301. OBJECT_ATTRIBUTES Obja;
  302. HANDLE Handle;
  303. UNICODE_STRING FileName;
  304. IO_STATUS_BLOCK IoStatusBlock;
  305. BOOLEAN TranslationStatus;
  306. RTL_RELATIVE_NAME_U RelativeName;
  307. PVOID FreeBuffer;
  308. ULONG CreateDisposition;
  309. ULONG CreateFlags;
  310. FILE_ALLOCATION_INFORMATION AllocationInfo;
  311. FILE_EA_INFORMATION EaInfo;
  312. PFILE_FULL_EA_INFORMATION EaBuffer;
  313. ULONG EaSize;
  314. PUNICODE_STRING lpConsoleName;
  315. BOOL bInheritHandle;
  316. BOOL EndsInSlash;
  317. DWORD SQOSFlags;
  318. BOOLEAN ContextTrackingMode = FALSE;
  319. BOOLEAN EffectiveOnly = FALSE;
  320. SECURITY_IMPERSONATION_LEVEL ImpersonationLevel = 0;
  321. SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
  322. HANDLE Heap;
  323. switch ( dwCreationDisposition ) {
  324. case CREATE_NEW :
  325. CreateDisposition = FILE_CREATE;
  326. break;
  327. case CREATE_ALWAYS :
  328. CreateDisposition = FILE_OVERWRITE_IF;
  329. break;
  330. case OPEN_EXISTING :
  331. CreateDisposition = FILE_OPEN;
  332. break;
  333. case OPEN_ALWAYS :
  334. CreateDisposition = FILE_OPEN_IF;
  335. break;
  336. case TRUNCATE_EXISTING :
  337. CreateDisposition = FILE_OPEN;
  338. if ( !(dwDesiredAccess & GENERIC_WRITE) ) {
  339. EtwpBaseSetLastNTError(STATUS_INVALID_PARAMETER);
  340. return INVALID_HANDLE_VALUE;
  341. }
  342. break;
  343. default :
  344. EtwpBaseSetLastNTError(STATUS_INVALID_PARAMETER);
  345. return INVALID_HANDLE_VALUE;
  346. }
  347. // temporary routing code
  348. RtlInitUnicodeString(&FileName,lpFileName);
  349. if ( FileName.Length > 1 && lpFileName[(FileName.Length >> 1)-1] == (WCHAR)'\\' ) {
  350. EndsInSlash = TRUE;
  351. }
  352. else {
  353. EndsInSlash = FALSE;
  354. }
  355. /*
  356. if ((lpConsoleName = EtwpBaseIsThisAConsoleName(&FileName,dwDesiredAccess)) ) {
  357. Handle = INVALID_HANDLE_VALUE;
  358. bInheritHandle = FALSE;
  359. if ( ARGUMENT_PRESENT(lpSecurityAttributes) ) {
  360. bInheritHandle = lpSecurityAttributes->bInheritHandle;
  361. }
  362. Handle = EtwpOpenConsoleW(lpConsoleName,
  363. dwDesiredAccess,
  364. bInheritHandle,
  365. FILE_SHARE_READ | FILE_SHARE_WRITE //dwShareMode
  366. );
  367. if ( Handle == INVALID_HANDLE_VALUE ) {
  368. EtwpBaseSetLastNTError(STATUS_ACCESS_DENIED);
  369. return INVALID_HANDLE_VALUE;
  370. }
  371. else {
  372. EtwpSetLastError(0);
  373. return Handle;
  374. }
  375. }*/
  376. // end temporary code
  377. CreateFlags = 0;
  378. TranslationStatus = RtlDosPathNameToRelativeNtPathName_U(
  379. lpFileName,
  380. &FileName,
  381. NULL,
  382. &RelativeName
  383. );
  384. if ( !TranslationStatus ) {
  385. EtwpSetLastError(ERROR_PATH_NOT_FOUND);
  386. return INVALID_HANDLE_VALUE;
  387. }
  388. FreeBuffer = FileName.Buffer;
  389. if ( RelativeName.RelativeName.Length ) {
  390. FileName = RelativeName.RelativeName;
  391. }
  392. else {
  393. RelativeName.ContainingDirectory = NULL;
  394. }
  395. InitializeObjectAttributes(
  396. &Obja,
  397. &FileName,
  398. (dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS) ? 0 : OBJ_CASE_INSENSITIVE,
  399. RelativeName.ContainingDirectory,
  400. NULL
  401. );
  402. SQOSFlags = dwFlagsAndAttributes & SECURITY_VALID_SQOS_FLAGS;
  403. if ( SQOSFlags & SECURITY_SQOS_PRESENT ) {
  404. SQOSFlags &= ~SECURITY_SQOS_PRESENT;
  405. if (SQOSFlags & SECURITY_CONTEXT_TRACKING) {
  406. SecurityQualityOfService.ContextTrackingMode = (SECURITY_CONTEXT_TRACKING_MODE) TRUE;
  407. SQOSFlags &= ~SECURITY_CONTEXT_TRACKING;
  408. } else {
  409. SecurityQualityOfService.ContextTrackingMode = (SECURITY_CONTEXT_TRACKING_MODE) FALSE;
  410. }
  411. if (SQOSFlags & SECURITY_EFFECTIVE_ONLY) {
  412. SecurityQualityOfService.EffectiveOnly = TRUE;
  413. SQOSFlags &= ~SECURITY_EFFECTIVE_ONLY;
  414. } else {
  415. SecurityQualityOfService.EffectiveOnly = FALSE;
  416. }
  417. SecurityQualityOfService.ImpersonationLevel = SQOSFlags >> 16;
  418. } else {
  419. SecurityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  420. SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation;
  421. SecurityQualityOfService.EffectiveOnly = TRUE;
  422. }
  423. SecurityQualityOfService.Length = sizeof( SECURITY_QUALITY_OF_SERVICE );
  424. Obja.SecurityQualityOfService = &SecurityQualityOfService;
  425. if ( ARGUMENT_PRESENT(lpSecurityAttributes) ) {
  426. Obja.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
  427. if ( lpSecurityAttributes->bInheritHandle ) {
  428. Obja.Attributes |= OBJ_INHERIT;
  429. }
  430. }
  431. EaBuffer = NULL;
  432. EaSize = 0;
  433. if ( ARGUMENT_PRESENT(hTemplateFile) ) {
  434. Status = NtQueryInformationFile(
  435. hTemplateFile,
  436. &IoStatusBlock,
  437. &EaInfo,
  438. sizeof(EaInfo),
  439. FileEaInformation
  440. );
  441. if ( NT_SUCCESS(Status) && EaInfo.EaSize ) {
  442. EaSize = EaInfo.EaSize;
  443. do {
  444. EaSize *= 2;
  445. EaBuffer = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), EaSize);
  446. if ( !EaBuffer ) {
  447. RtlReleaseRelativeName(&RelativeName);
  448. RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
  449. EtwpBaseSetLastNTError(STATUS_NO_MEMORY);
  450. return INVALID_HANDLE_VALUE;
  451. }
  452. Status = NtQueryEaFile(
  453. hTemplateFile,
  454. &IoStatusBlock,
  455. EaBuffer,
  456. EaSize,
  457. FALSE,
  458. (PVOID)NULL,
  459. 0,
  460. (PULONG)NULL,
  461. TRUE
  462. );
  463. if ( !NT_SUCCESS(Status) ) {
  464. RtlFreeHeap(RtlProcessHeap(), 0,EaBuffer);
  465. EaBuffer = NULL;
  466. IoStatusBlock.Information = 0;
  467. }
  468. } while ( Status == STATUS_BUFFER_OVERFLOW ||
  469. Status == STATUS_BUFFER_TOO_SMALL );
  470. EaSize = (ULONG)IoStatusBlock.Information;
  471. }
  472. }
  473. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING ? FILE_NO_INTERMEDIATE_BUFFERING : 0 );
  474. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH ? FILE_WRITE_THROUGH : 0 );
  475. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED ? 0 : FILE_SYNCHRONOUS_IO_NONALERT );
  476. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN ? FILE_SEQUENTIAL_ONLY : 0 );
  477. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS ? FILE_RANDOM_ACCESS : 0 );
  478. CreateFlags |= (dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS ? FILE_OPEN_FOR_BACKUP_INTENT : 0 );
  479. if ( dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE ) {
  480. CreateFlags |= FILE_DELETE_ON_CLOSE;
  481. dwDesiredAccess |= DELETE;
  482. }
  483. if ( dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT ) {
  484. CreateFlags |= FILE_OPEN_REPARSE_POINT;
  485. }
  486. if ( dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL ) {
  487. CreateFlags |= FILE_OPEN_NO_RECALL;
  488. }
  489. //
  490. // Backup semantics allow directories to be opened
  491. //
  492. if ( !(dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS) ) {
  493. CreateFlags |= FILE_NON_DIRECTORY_FILE;
  494. }
  495. else {
  496. //
  497. // Backup intent was specified... Now look to see if we are to allow
  498. // directory creation
  499. //
  500. if ( (dwFlagsAndAttributes & FILE_ATTRIBUTE_DIRECTORY ) &&
  501. (dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS ) &&
  502. (CreateDisposition == FILE_CREATE) ) {
  503. CreateFlags |= FILE_DIRECTORY_FILE;
  504. }
  505. }
  506. Status = NtCreateFile(
  507. &Handle,
  508. (ACCESS_MASK)dwDesiredAccess | SYNCHRONIZE | FILE_READ_ATTRIBUTES,
  509. &Obja,
  510. &IoStatusBlock,
  511. NULL,
  512. dwFlagsAndAttributes & (FILE_ATTRIBUTE_VALID_FLAGS & ~FILE_ATTRIBUTE_DIRECTORY),
  513. dwShareMode,
  514. CreateDisposition,
  515. CreateFlags,
  516. EaBuffer,
  517. EaSize
  518. );
  519. RtlReleaseRelativeName(&RelativeName);
  520. RtlFreeHeap(Heap = RtlProcessHeap(), 0,FreeBuffer);
  521. RtlFreeHeap(Heap, 0, EaBuffer);
  522. if ( !NT_SUCCESS(Status) ) {
  523. EtwpBaseSetLastNTError(Status);
  524. if ( Status == STATUS_OBJECT_NAME_COLLISION ) {
  525. EtwpSetLastError(ERROR_FILE_EXISTS);
  526. }
  527. else if ( Status == STATUS_FILE_IS_A_DIRECTORY ) {
  528. if ( EndsInSlash ) {
  529. EtwpSetLastError(ERROR_PATH_NOT_FOUND);
  530. }
  531. else {
  532. EtwpSetLastError(ERROR_ACCESS_DENIED);
  533. }
  534. }
  535. return INVALID_HANDLE_VALUE;
  536. }
  537. //
  538. // if NT returns supersede/overwritten, it means that a create_always, openalways
  539. // found an existing copy of the file. In this case ERROR_ALREADY_EXISTS is returned
  540. //
  541. if ( (dwCreationDisposition == CREATE_ALWAYS && IoStatusBlock.Information == FILE_OVERWRITTEN) ||
  542. (dwCreationDisposition == OPEN_ALWAYS && IoStatusBlock.Information == FILE_OPENED) ){
  543. EtwpSetLastError(ERROR_ALREADY_EXISTS);
  544. }
  545. else {
  546. EtwpSetLastError(0);
  547. }
  548. //
  549. // Truncate the file if required
  550. //
  551. if ( dwCreationDisposition == TRUNCATE_EXISTING) {
  552. AllocationInfo.AllocationSize.QuadPart = 0;
  553. Status = NtSetInformationFile(
  554. Handle,
  555. &IoStatusBlock,
  556. &AllocationInfo,
  557. sizeof(AllocationInfo),
  558. FileAllocationInformation
  559. );
  560. if ( !NT_SUCCESS(Status) ) {
  561. EtwpBaseSetLastNTError(Status);
  562. NtClose(Handle);
  563. Handle = INVALID_HANDLE_VALUE;
  564. }
  565. }
  566. //
  567. // Deal with hTemplateFile
  568. //
  569. return Handle;
  570. }
  571. HANDLE
  572. EtwpBaseGetNamedObjectDirectory(
  573. VOID
  574. )
  575. {
  576. OBJECT_ATTRIBUTES Obja;
  577. NTSTATUS Status;
  578. UNICODE_STRING RestrictedObjectDirectory;
  579. ACCESS_MASK DirAccess = DIRECTORY_ALL_ACCESS &
  580. ~(DELETE | WRITE_DAC | WRITE_OWNER);
  581. HANDLE hRootNamedObject;
  582. HANDLE BaseHandle;
  583. if ( BaseNamedObjectDirectory != NULL) {
  584. return BaseNamedObjectDirectory;
  585. }
  586. RtlAcquirePebLock();
  587. if ( !BaseNamedObjectDirectory ) {
  588. PBASE_STATIC_SERVER_DATA tmpBaseStaticServerData = BASE_SHARED_SERVER_DATA;
  589. BASE_READ_REMOTE_STR_TEMP(TempStr);
  590. InitializeObjectAttributes( &Obja,
  591. BASE_READ_REMOTE_STR(tmpBaseStaticServerData->NamedObjectDirectory, TempStr),
  592. OBJ_CASE_INSENSITIVE,
  593. NULL,
  594. NULL
  595. );
  596. Status = NtOpenDirectoryObject( &BaseHandle,
  597. DirAccess,
  598. &Obja
  599. );
  600. // if the intial open failed, try again with just traverse, and
  601. // open the restricted subdirectory
  602. if ( !NT_SUCCESS(Status) ) {
  603. Status = NtOpenDirectoryObject( &hRootNamedObject,
  604. DIRECTORY_TRAVERSE,
  605. &Obja
  606. );
  607. if ( NT_SUCCESS(Status) ) {
  608. RtlInitUnicodeString( &RestrictedObjectDirectory, L"Restricted");
  609. InitializeObjectAttributes( &Obja,
  610. &RestrictedObjectDirectory,
  611. OBJ_CASE_INSENSITIVE,
  612. hRootNamedObject,
  613. NULL
  614. );
  615. Status = NtOpenDirectoryObject( &BaseHandle,
  616. DirAccess,
  617. &Obja
  618. );
  619. NtClose( hRootNamedObject );
  620. }
  621. }
  622. if ( NT_SUCCESS(Status) ) {
  623. BaseNamedObjectDirectory = BaseHandle;
  624. }
  625. }
  626. RtlReleasePebLock();
  627. return BaseNamedObjectDirectory;
  628. }
  629. POBJECT_ATTRIBUTES
  630. EtwpBaseFormatObjectAttributes(
  631. OUT POBJECT_ATTRIBUTES ObjectAttributes,
  632. IN PSECURITY_ATTRIBUTES SecurityAttributes,
  633. IN PUNICODE_STRING ObjectName
  634. )
  635. /*++
  636. Routine Description:
  637. This function transforms a Win32 security attributes structure into
  638. an NT object attributes structure. It returns the address of the
  639. resulting structure (or NULL if SecurityAttributes was not
  640. specified).
  641. Arguments:
  642. ObjectAttributes - Returns an initialized NT object attributes
  643. structure that contains a superset of the information provided
  644. by the security attributes structure.
  645. SecurityAttributes - Supplies the address of a security attributes
  646. structure that needs to be transformed into an NT object
  647. attributes structure.
  648. ObjectName - Supplies a name for the object relative to the
  649. BaseNamedObjectDirectory object directory.
  650. Return Value:
  651. NULL - A value of null should be used to mimic the behavior of the
  652. specified SecurityAttributes structure.
  653. NON-NULL - Returns the ObjectAttributes value. The structure is
  654. properly initialized by this function.
  655. --*/
  656. {
  657. HANDLE RootDirectory;
  658. ULONG Attributes;
  659. PVOID SecurityDescriptor;
  660. if ( ARGUMENT_PRESENT(SecurityAttributes) ||
  661. ARGUMENT_PRESENT(ObjectName) ) {
  662. if ( SecurityAttributes ) {
  663. Attributes = (SecurityAttributes->bInheritHandle ? OBJ_INHERIT : 0);
  664. SecurityDescriptor = SecurityAttributes->lpSecurityDescriptor;
  665. }
  666. else {
  667. Attributes = 0;
  668. SecurityDescriptor = NULL;
  669. }
  670. if ( ARGUMENT_PRESENT(ObjectName) ) {
  671. Attributes |= OBJ_OPENIF;
  672. RootDirectory = EtwpBaseGetNamedObjectDirectory();
  673. }
  674. else {
  675. RootDirectory = NULL;
  676. }
  677. InitializeObjectAttributes(
  678. ObjectAttributes,
  679. ObjectName,
  680. Attributes,
  681. RootDirectory,
  682. SecurityDescriptor
  683. );
  684. return ObjectAttributes;
  685. }
  686. else {
  687. return NULL;
  688. }
  689. }
  690. HANDLE
  691. APIENTRY
  692. EtwpCreateEventW(
  693. LPSECURITY_ATTRIBUTES lpEventAttributes,
  694. BOOL bManualReset,
  695. BOOL bInitialState,
  696. LPCWSTR lpName
  697. )
  698. /*++
  699. Routine Description:
  700. An event object is created and a handle opened for access to the
  701. object with the CreateEvent function.
  702. The CreateEvent function creates an event object with the specified
  703. initial state. If an event is in the Signaled state (TRUE), a wait
  704. operation on the event does not block. If the event is in the Not-
  705. Signaled state (FALSE), a wait operation on the event blocks until
  706. the specified event attains a state of Signaled, or the timeout
  707. value is exceeded.
  708. In addition to the STANDARD_RIGHTS_REQUIRED access flags, the following
  709. object type specific access flags are valid for event objects:
  710. - EVENT_MODIFY_STATE - Modify state access (set and reset) to
  711. the event is desired.
  712. - SYNCHRONIZE - Synchronization access (wait) to the event is
  713. desired.
  714. - EVENT_ALL_ACCESS - This set of access flags specifies all of
  715. the possible access flags for an event object.
  716. Arguments:
  717. lpEventAttributes - An optional parameter that may be used to
  718. specify the attributes of the new event. If the parameter is
  719. not specified, then the event is created without a security
  720. descriptor, and the resulting handle is not inherited on process
  721. creation.
  722. bManualReset - Supplies a flag which if TRUE specifies that the
  723. event must be manually reset. If the value is FALSE, then after
  724. releasing a single waiter, the system automaticaly resets the
  725. event.
  726. bInitialState - The initial state of the event object, one of TRUE
  727. or FALSE. If the InitialState is specified as TRUE, the event's
  728. current state value is set to one, otherwise it is set to zero.
  729. lpName - Optional unicode name of event
  730. Return Value:
  731. NON-NULL - Returns a handle to the new event. The handle has full
  732. access to the new event and may be used in any API that requires
  733. a handle to an event object.
  734. FALSE/NULL - The operation failed. Extended error status is available
  735. using EtwpGetLastError.
  736. --*/
  737. {
  738. NTSTATUS Status;
  739. OBJECT_ATTRIBUTES Obja;
  740. POBJECT_ATTRIBUTES pObja;
  741. HANDLE Handle;
  742. UNICODE_STRING ObjectName;
  743. if ( ARGUMENT_PRESENT(lpName) ) {
  744. RtlInitUnicodeString(&ObjectName,lpName);
  745. pObja = EtwpBaseFormatObjectAttributes(&Obja,lpEventAttributes,&ObjectName);
  746. }
  747. else {
  748. pObja = EtwpBaseFormatObjectAttributes(&Obja,lpEventAttributes,NULL);
  749. }
  750. Status = NtCreateEvent(
  751. &Handle,
  752. EVENT_ALL_ACCESS,
  753. pObja,
  754. bManualReset ? NotificationEvent : SynchronizationEvent,
  755. (BOOLEAN)bInitialState
  756. );
  757. if ( NT_SUCCESS(Status) ) {
  758. if ( Status == STATUS_OBJECT_NAME_EXISTS ) {
  759. EtwpSetLastError(ERROR_ALREADY_EXISTS);
  760. }
  761. else {
  762. EtwpSetLastError(0);
  763. }
  764. return Handle;
  765. }
  766. else {
  767. EtwpBaseSetLastNTError(Status);
  768. return NULL;
  769. }
  770. }
  771. //
  772. // Event Services
  773. //
  774. DWORD
  775. WINAPI
  776. EtwpSetFilePointer(
  777. HANDLE hFile,
  778. LONG lDistanceToMove,
  779. PLONG lpDistanceToMoveHigh,
  780. DWORD dwMoveMethod
  781. )
  782. /*++
  783. Routine Description:
  784. An open file's file pointer can be set using SetFilePointer.
  785. The purpose of this function is to update the current value of a
  786. file's file pointer. Care should be taken in multi-threaded
  787. applications that have multiple threads sharing a file handle with
  788. each thread updating the file pointer and then doing a read. This
  789. sequence should be treated as a critical section of code and should
  790. be protected using either a critical section object or a mutex
  791. object.
  792. This API provides the same functionality as DOS (int 21h, function
  793. 42h) and OS/2's DosSetFilePtr.
  794. Arguments:
  795. hFile - Supplies an open handle to a file whose file pointer is to be
  796. moved. The file handle must have been created with
  797. GENERIC_READ or GENERIC_WRITE access to the file.
  798. lDistanceToMove - Supplies the number of bytes to move the file
  799. pointer. A positive value moves the pointer forward in the file
  800. and a negative value moves backwards in the file.
  801. lpDistanceToMoveHigh - An optional parameter that if specified
  802. supplies the high order 32-bits of the 64-bit distance to move.
  803. If the value of this parameter is NULL, this API can only
  804. operate on files whose maximum size is (2**32)-2. If this
  805. parameter is specified, than the maximum file size is (2**64)-2.
  806. This value also returns the high order 32-bits of the new value
  807. of the file pointer. If this value, and the return value
  808. are 0xffffffff, then an error is indicated.
  809. dwMoveMethod - Supplies a value that specifies the starting point
  810. for the file pointer move.
  811. FILE_BEGIN - The starting point is zero or the beginning of the
  812. file. If FILE_BEGIN is specified, then DistanceToMove is
  813. interpreted as an unsigned location for the new
  814. file pointer.
  815. FILE_CURRENT - The current value of the file pointer is used as
  816. the starting point.
  817. FILE_END - The current end of file position is used as the
  818. starting point.
  819. Return Value:
  820. Not -1 - Returns the low order 32-bits of the new value of the file
  821. pointer.
  822. 0xffffffff - If the value of lpDistanceToMoveHigh was NULL, then The
  823. operation failed. Extended error status is available using
  824. EtwpGetLastError. Otherwise, this is the low order 32-bits of the
  825. new value of the file pointer.
  826. --*/
  827. {
  828. NTSTATUS Status;
  829. IO_STATUS_BLOCK IoStatusBlock;
  830. FILE_POSITION_INFORMATION CurrentPosition;
  831. FILE_STANDARD_INFORMATION StandardInfo;
  832. LARGE_INTEGER Large;
  833. if (CONSOLE_HANDLE(hFile)) {
  834. EtwpBaseSetLastNTError(STATUS_INVALID_HANDLE);
  835. return (DWORD)-1;
  836. }
  837. if (ARGUMENT_PRESENT(lpDistanceToMoveHigh)) {
  838. Large.HighPart = *lpDistanceToMoveHigh;
  839. Large.LowPart = lDistanceToMove;
  840. }
  841. else {
  842. Large.QuadPart = lDistanceToMove;
  843. }
  844. switch (dwMoveMethod) {
  845. case FILE_BEGIN :
  846. CurrentPosition.CurrentByteOffset = Large;
  847. break;
  848. case FILE_CURRENT :
  849. //
  850. // Get the current position of the file pointer
  851. //
  852. Status = NtQueryInformationFile(
  853. hFile,
  854. &IoStatusBlock,
  855. &CurrentPosition,
  856. sizeof(CurrentPosition),
  857. FilePositionInformation
  858. );
  859. if ( !NT_SUCCESS(Status) ) {
  860. EtwpBaseSetLastNTError(Status);
  861. return (DWORD)-1;
  862. }
  863. CurrentPosition.CurrentByteOffset.QuadPart += Large.QuadPart;
  864. break;
  865. case FILE_END :
  866. Status = NtQueryInformationFile(
  867. hFile,
  868. &IoStatusBlock,
  869. &StandardInfo,
  870. sizeof(StandardInfo),
  871. FileStandardInformation
  872. );
  873. if ( !NT_SUCCESS(Status) ) {
  874. EtwpBaseSetLastNTError(Status);
  875. return (DWORD)-1;
  876. }
  877. CurrentPosition.CurrentByteOffset.QuadPart =
  878. StandardInfo.EndOfFile.QuadPart + Large.QuadPart;
  879. break;
  880. default:
  881. EtwpSetLastError(ERROR_INVALID_PARAMETER);
  882. return (DWORD)-1;
  883. break;
  884. }
  885. //
  886. // If the resulting file position is negative, or if the app is not
  887. // prepared for greater than
  888. // then 32 bits than fail
  889. //
  890. if ( CurrentPosition.CurrentByteOffset.QuadPart < 0 ) {
  891. EtwpSetLastError(ERROR_NEGATIVE_SEEK);
  892. return (DWORD)-1;
  893. }
  894. if ( !ARGUMENT_PRESENT(lpDistanceToMoveHigh) &&
  895. (CurrentPosition.CurrentByteOffset.HighPart & MAXLONG) ) {
  896. EtwpSetLastError(ERROR_INVALID_PARAMETER);
  897. return (DWORD)-1;
  898. }
  899. //
  900. // Set the current file position
  901. //
  902. Status = NtSetInformationFile(
  903. hFile,
  904. &IoStatusBlock,
  905. &CurrentPosition,
  906. sizeof(CurrentPosition),
  907. FilePositionInformation
  908. );
  909. if ( NT_SUCCESS(Status) ) {
  910. if (ARGUMENT_PRESENT(lpDistanceToMoveHigh)){
  911. *lpDistanceToMoveHigh = CurrentPosition.CurrentByteOffset.HighPart;
  912. }
  913. if ( CurrentPosition.CurrentByteOffset.LowPart == -1 ) {
  914. EtwpSetLastError(0);
  915. }
  916. return CurrentPosition.CurrentByteOffset.LowPart;
  917. }
  918. else {
  919. EtwpBaseSetLastNTError(Status);
  920. if (ARGUMENT_PRESENT(lpDistanceToMoveHigh)){
  921. *lpDistanceToMoveHigh = -1;
  922. }
  923. return (DWORD)-1;
  924. }
  925. }
  926. BOOL
  927. WINAPI
  928. EtwpReadFile(
  929. HANDLE hFile,
  930. LPVOID lpBuffer,
  931. DWORD nNumberOfBytesToRead,
  932. LPDWORD lpNumberOfBytesRead,
  933. LPOVERLAPPED lpOverlapped
  934. )
  935. /*++
  936. Routine Description:
  937. Data can be read from a file using ReadFile.
  938. This API is used to read data from a file. Data is read from the
  939. file from the position indicated by the file pointer. After the
  940. read completes, the file pointer is adjusted by the number of bytes
  941. actually read. A return value of TRUE coupled with a bytes read of
  942. 0 indicates that the file pointer was beyond the current end of the
  943. file at the time of the read.
  944. Arguments:
  945. hFile - Supplies an open handle to a file that is to be read. The
  946. file handle must have been created with GENERIC_READ access to
  947. the file.
  948. lpBuffer - Supplies the address of a buffer to receive the data read
  949. from the file.
  950. nNumberOfBytesToRead - Supplies the number of bytes to read from the
  951. file.
  952. lpNumberOfBytesRead - Returns the number of bytes read by this call.
  953. This parameter is always set to 0 before doing any IO or error
  954. checking.
  955. lpOverlapped - Optionally points to an OVERLAPPED structure to be used with the
  956. request. If NULL then the transfer starts at the current file position
  957. and ReadFile will not return until the operation completes.
  958. If the handle hFile was created without specifying FILE_FLAG_OVERLAPPED
  959. the file pointer is moved to the specified offset plus
  960. lpNumberOfBytesRead before ReadFile returns. ReadFile will wait for the
  961. request to complete before returning (it will not return
  962. ERROR_IO_PENDING).
  963. When FILE_FLAG_OVERLAPPED is specified, ReadFile may return
  964. ERROR_IO_PENDING to allow the calling function to continue processing
  965. while the operation completes. The event (or hFile if hEvent is NULL) will
  966. be set to the signalled state upon completion of the request.
  967. When the handle is created with FILE_FLAG_OVERLAPPED and lpOverlapped
  968. is set to NULL, ReadFile will return ERROR_INVALID_PARAMTER because
  969. the file offset is required.
  970. Return Value:
  971. TRUE - The operation was successul.
  972. FALSE - The operation failed. Extended error status is available
  973. using EtwpGetLastError.
  974. --*/
  975. {
  976. NTSTATUS Status;
  977. IO_STATUS_BLOCK IoStatusBlock;
  978. PPEB Peb;
  979. DWORD InputMode;
  980. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) ) {
  981. *lpNumberOfBytesRead = 0;
  982. }
  983. Peb = NtCurrentPeb();
  984. switch( HandleToUlong(hFile) ) {
  985. case STD_INPUT_HANDLE: hFile = Peb->ProcessParameters->StandardInput;
  986. break;
  987. case STD_OUTPUT_HANDLE: hFile = Peb->ProcessParameters->StandardOutput;
  988. break;
  989. case STD_ERROR_HANDLE: hFile = Peb->ProcessParameters->StandardError;
  990. break;
  991. }
  992. if ( ARGUMENT_PRESENT( lpOverlapped ) ) {
  993. LARGE_INTEGER Li;
  994. lpOverlapped->Internal = (DWORD)STATUS_PENDING;
  995. Li.LowPart = lpOverlapped->Offset;
  996. Li.HighPart = lpOverlapped->OffsetHigh;
  997. Status = NtReadFile(
  998. hFile,
  999. lpOverlapped->hEvent,
  1000. NULL,
  1001. (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped,
  1002. (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  1003. lpBuffer,
  1004. nNumberOfBytesToRead,
  1005. &Li,
  1006. NULL
  1007. );
  1008. if ( NT_SUCCESS(Status) && Status != STATUS_PENDING) {
  1009. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) ) {
  1010. try {
  1011. *lpNumberOfBytesRead = (DWORD)lpOverlapped->InternalHigh;
  1012. }
  1013. except(EXCEPTION_EXECUTE_HANDLER) {
  1014. *lpNumberOfBytesRead = 0;
  1015. }
  1016. }
  1017. return TRUE;
  1018. }
  1019. else
  1020. if (Status == STATUS_END_OF_FILE) {
  1021. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) ) {
  1022. *lpNumberOfBytesRead = 0;
  1023. }
  1024. EtwpBaseSetLastNTError(Status);
  1025. return FALSE;
  1026. }
  1027. else {
  1028. EtwpBaseSetLastNTError(Status);
  1029. return FALSE;
  1030. }
  1031. }
  1032. else
  1033. {
  1034. Status = NtReadFile(
  1035. hFile,
  1036. NULL,
  1037. NULL,
  1038. NULL,
  1039. &IoStatusBlock,
  1040. lpBuffer,
  1041. nNumberOfBytesToRead,
  1042. NULL,
  1043. NULL
  1044. );
  1045. if ( Status == STATUS_PENDING) {
  1046. // Operation must complete before return & IoStatusBlock destroyed
  1047. Status = NtWaitForSingleObject( hFile, FALSE, NULL );
  1048. if ( NT_SUCCESS(Status)) {
  1049. Status = IoStatusBlock.Status;
  1050. }
  1051. }
  1052. if ( NT_SUCCESS(Status) ) {
  1053. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) ) {
  1054. *lpNumberOfBytesRead = (DWORD)IoStatusBlock.Information;
  1055. }
  1056. return TRUE;
  1057. }
  1058. else
  1059. if (Status == STATUS_END_OF_FILE) {
  1060. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) ) {
  1061. *lpNumberOfBytesRead = 0;
  1062. }
  1063. return TRUE;
  1064. }
  1065. else {
  1066. if ( NT_WARNING(Status) && ARGUMENT_PRESENT(lpNumberOfBytesRead)) {
  1067. *lpNumberOfBytesRead = (DWORD)IoStatusBlock.Information;
  1068. }
  1069. EtwpBaseSetLastNTError(Status);
  1070. return FALSE;
  1071. }
  1072. }
  1073. }
  1074. BOOL
  1075. EtwpCloseHandle(
  1076. HANDLE hObject
  1077. )
  1078. {
  1079. NTSTATUS Status;
  1080. Status = NtClose(hObject);
  1081. if ( NT_SUCCESS(Status) ) {
  1082. return TRUE;
  1083. } else {
  1084. EtwpBaseSetLastNTError(Status);
  1085. return FALSE;
  1086. }
  1087. }
  1088. DWORD
  1089. APIENTRY
  1090. EtwpWaitForSingleObjectEx(
  1091. HANDLE hHandle,
  1092. DWORD dwMilliseconds,
  1093. BOOL bAlertable
  1094. )
  1095. /*++
  1096. Routine Description:
  1097. A wait operation on a waitable object is accomplished with the
  1098. WaitForSingleObjectEx function.
  1099. Waiting on an object checks the current state of the object. If the
  1100. current state of the object allows continued execution, any
  1101. adjustments to the object state are made (for example, decrementing
  1102. the semaphore count for a semaphore object) and the thread continues
  1103. execution. If the current state of the object does not allow
  1104. continued execution, the thread is placed into the wait state
  1105. pending the change of the object's state or time-out.
  1106. If the bAlertable parameter is FALSE, the only way the wait
  1107. terminates is because the specified timeout period expires, or
  1108. because the specified object entered the signaled state. If the
  1109. bAlertable parameter is TRUE, then the wait can return due to any
  1110. one of the above wait termination conditions, or because an I/O
  1111. completion callback terminated the wait early (return value of
  1112. WAIT_IO_COMPLETION).
  1113. Arguments:
  1114. hHandle - An open handle to a waitable object. The handle must have
  1115. SYNCHRONIZE access to the object.
  1116. dwMilliseconds - A time-out value that specifies the relative time,
  1117. in milliseconds, over which the wait is to be completed. A
  1118. timeout value of 0 specified that the wait is to timeout
  1119. immediately. This allows an application to test an object to
  1120. determine if it is in the signaled state. A timeout value of
  1121. 0xffffffff specifies an infinite timeout period.
  1122. bAlertable - Supplies a flag that controls whether or not the
  1123. wait may terminate early due to an I/O completion callback.
  1124. A value of TRUE allows this API to complete early due to an I/O
  1125. completion callback. A value of FALSE will not allow I/O
  1126. completion callbacks to terminate this call early.
  1127. Return Value:
  1128. WAIT_TIME_OUT - Indicates that the wait was terminated due to the
  1129. TimeOut conditions.
  1130. 0 - indicates the specified object attained a Signaled
  1131. state thus completing the wait.
  1132. 0xffffffff - The wait terminated due to an error. EtwpGetLastError may be
  1133. used to get additional error information.
  1134. WAIT_ABANDONED - indicates the specified object attained a Signaled
  1135. state but was abandoned.
  1136. WAIT_IO_COMPLETION - The wait terminated due to one or more I/O
  1137. completion callbacks.
  1138. --*/
  1139. {
  1140. NTSTATUS Status;
  1141. LARGE_INTEGER TimeOut;
  1142. PLARGE_INTEGER pTimeOut;
  1143. PPEB Peb;
  1144. RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME Frame = { sizeof(Frame), RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER };
  1145. RtlActivateActivationContextUnsafeFast(&Frame, NULL); // make the process default activation context active so that APCs are delivered under it
  1146. __try {
  1147. Peb = NtCurrentPeb();
  1148. switch( HandleToUlong(hHandle) ) {
  1149. case STD_INPUT_HANDLE: hHandle = Peb->ProcessParameters->StandardInput;
  1150. break;
  1151. case STD_OUTPUT_HANDLE: hHandle = Peb->ProcessParameters->StandardOutput;
  1152. break;
  1153. case STD_ERROR_HANDLE: hHandle = Peb->ProcessParameters->StandardError;
  1154. break;
  1155. }
  1156. pTimeOut = EtwpBaseFormatTimeOut(&TimeOut,dwMilliseconds);
  1157. rewait:
  1158. Status = NtWaitForSingleObject(hHandle,(BOOLEAN)bAlertable,pTimeOut);
  1159. if ( !NT_SUCCESS(Status) ) {
  1160. EtwpBaseSetLastNTError(Status);
  1161. Status = (NTSTATUS)0xffffffff;
  1162. }
  1163. else {
  1164. if ( bAlertable && Status == STATUS_ALERTED ) {
  1165. goto rewait;
  1166. }
  1167. }
  1168. } __finally {
  1169. RtlDeactivateActivationContextUnsafeFast(&Frame);
  1170. }
  1171. return (DWORD)Status;
  1172. }
  1173. BOOL
  1174. WINAPI
  1175. EtwpGetOverlappedResult(
  1176. HANDLE hFile,
  1177. LPOVERLAPPED lpOverlapped,
  1178. LPDWORD lpNumberOfBytesTransferred,
  1179. BOOL bWait
  1180. )
  1181. /*++
  1182. Routine Description:
  1183. The GetOverlappedResult function returns the result of the last
  1184. operation that used lpOverlapped and returned ERROR_IO_PENDING.
  1185. Arguments:
  1186. hFile - Supplies the open handle to the file that the overlapped
  1187. structure lpOverlapped was supplied to ReadFile, WriteFile,
  1188. ConnectNamedPipe, WaitNamedPipe or TransactNamedPipe.
  1189. lpOverlapped - Points to an OVERLAPPED structure previously supplied to
  1190. ReadFile, WriteFile, ConnectNamedPipe, WaitNamedPipe or
  1191. TransactNamedPipe.
  1192. lpNumberOfBytesTransferred - Returns the number of bytes transferred
  1193. by the operation.
  1194. bWait - A boolean value that affects the behavior when the operation
  1195. is still in progress. If TRUE and the operation is still in progress,
  1196. GetOverlappedResult will wait for the operation to complete before
  1197. returning. If FALSE and the operation is incomplete,
  1198. GetOverlappedResult will return FALSE. In this case the extended
  1199. error information available from the EtwpGetLastError function will be
  1200. set to ERROR_IO_INCOMPLETE.
  1201. Return Value:
  1202. TRUE -- The operation was successful, the pipe is in the
  1203. connected state.
  1204. FALSE -- The operation failed. Extended error status is available using
  1205. EtwpGetLastError.
  1206. --*/
  1207. {
  1208. DWORD WaitReturn;
  1209. //
  1210. // Did caller specify an event to the original operation or was the
  1211. // default (file handle) used?
  1212. //
  1213. if (lpOverlapped->Internal == (DWORD)STATUS_PENDING ) {
  1214. if ( bWait ) {
  1215. WaitReturn = EtwpWaitForSingleObject(
  1216. ( lpOverlapped->hEvent != NULL ) ?
  1217. lpOverlapped->hEvent : hFile,
  1218. INFINITE
  1219. );
  1220. }
  1221. else {
  1222. WaitReturn = WAIT_TIMEOUT;
  1223. }
  1224. if ( WaitReturn == WAIT_TIMEOUT ) {
  1225. // !bWait and event in not signalled state
  1226. EtwpSetLastError( ERROR_IO_INCOMPLETE );
  1227. return FALSE;
  1228. }
  1229. if ( WaitReturn != 0 ) {
  1230. return FALSE; // WaitForSingleObject calls BaseSetLastError
  1231. }
  1232. }
  1233. *lpNumberOfBytesTransferred = (DWORD)lpOverlapped->InternalHigh;
  1234. if ( NT_SUCCESS((NTSTATUS)lpOverlapped->Internal) ){
  1235. return TRUE;
  1236. }
  1237. else {
  1238. EtwpBaseSetLastNTError( (NTSTATUS)lpOverlapped->Internal );
  1239. return FALSE;
  1240. }
  1241. }
  1242. PLARGE_INTEGER
  1243. EtwpBaseFormatTimeOut(
  1244. OUT PLARGE_INTEGER TimeOut,
  1245. IN DWORD Milliseconds
  1246. )
  1247. /*++
  1248. Routine Description:
  1249. This function translates a Win32 style timeout to an NT relative
  1250. timeout value.
  1251. Arguments:
  1252. TimeOut - Returns an initialized NT timeout value that is equivalent
  1253. to the Milliseconds parameter.
  1254. Milliseconds - Supplies the timeout value in milliseconds. A value
  1255. of -1 indicates indefinite timeout.
  1256. Return Value:
  1257. NULL - A value of null should be used to mimic the behavior of the
  1258. specified Milliseconds parameter.
  1259. NON-NULL - Returns the TimeOut value. The structure is properly
  1260. initialized by this function.
  1261. --*/
  1262. {
  1263. if ( (LONG) Milliseconds == -1 ) {
  1264. return( NULL );
  1265. }
  1266. TimeOut->QuadPart = UInt32x32To64( Milliseconds, 10000 );
  1267. TimeOut->QuadPart *= -1;
  1268. return TimeOut;
  1269. }
  1270. DWORD
  1271. EtwpWaitForSingleObject(
  1272. HANDLE hHandle,
  1273. DWORD dwMilliseconds
  1274. )
  1275. /*++
  1276. Routine Description:
  1277. A wait operation on a waitable object is accomplished with the
  1278. WaitForSingleObject function.
  1279. Waiting on an object checks the current state of the object. If the
  1280. current state of the object allows continued execution, any
  1281. adjustments to the object state are made (for example, decrementing
  1282. the semaphore count for a semaphore object) and the thread continues
  1283. execution. If the current state of the object does not allow
  1284. continued execution, the thread is placed into the wait state
  1285. pending the change of the object's state or time-out.
  1286. Arguments:
  1287. hHandle - An open handle to a waitable object. The handle must have
  1288. SYNCHRONIZE access to the object.
  1289. dwMilliseconds - A time-out value that specifies the relative time,
  1290. in milliseconds, over which the wait is to be completed. A
  1291. timeout value of 0 specified that the wait is to timeout
  1292. immediately. This allows an application to test an object to
  1293. determine if it is in the signaled state. A timeout value of -1
  1294. specifies an infinite timeout period.
  1295. Return Value:
  1296. WAIT_TIME_OUT - Indicates that the wait was terminated due to the
  1297. TimeOut conditions.
  1298. 0 - indicates the specified object attained a Signaled
  1299. state thus completing the wait.
  1300. WAIT_ABANDONED - indicates the specified object attained a Signaled
  1301. state but was abandoned.
  1302. --*/
  1303. {
  1304. return EtwpWaitForSingleObjectEx(hHandle,dwMilliseconds,FALSE);
  1305. }
  1306. BOOL
  1307. WINAPI
  1308. EtwpDeviceIoControl(
  1309. HANDLE hDevice,
  1310. DWORD dwIoControlCode,
  1311. LPVOID lpInBuffer,
  1312. DWORD nInBufferSize,
  1313. LPVOID lpOutBuffer,
  1314. DWORD nOutBufferSize,
  1315. LPDWORD lpBytesReturned,
  1316. LPOVERLAPPED lpOverlapped
  1317. )
  1318. /*++
  1319. Routine Description:
  1320. An operation on a device may be performed by calling the device driver
  1321. directly using the DeviceIoContrl function.
  1322. The device driver must first be opened to get a valid handle.
  1323. Arguments:
  1324. hDevice - Supplies an open handle a device on which the operation is to
  1325. be performed.
  1326. dwIoControlCode - Supplies the control code for the operation. This
  1327. control code determines on which type of device the operation must
  1328. be performed and determines exactly what operation is to be
  1329. performed.
  1330. lpInBuffer - Suplies an optional pointer to an input buffer that contains
  1331. the data required to perform the operation. Whether or not the
  1332. buffer is actually optional is dependent on the IoControlCode.
  1333. nInBufferSize - Supplies the length of the input buffer in bytes.
  1334. lpOutBuffer - Suplies an optional pointer to an output buffer into which
  1335. the output data will be copied. Whether or not the buffer is actually
  1336. optional is dependent on the IoControlCode.
  1337. nOutBufferSize - Supplies the length of the output buffer in bytes.
  1338. lpBytesReturned - Supplies a pointer to a dword which will receive the
  1339. actual length of the data returned in the output buffer.
  1340. lpOverlapped - An optional parameter that supplies an overlap structure to
  1341. be used with the request. If NULL or the handle was created without
  1342. FILE_FLAG_OVERLAPPED then the DeviceIoControl will not return until
  1343. the operation completes.
  1344. When lpOverlapped is supplied and FILE_FLAG_OVERLAPPED was specified
  1345. when the handle was created, DeviceIoControl may return
  1346. ERROR_IO_PENDING to allow the caller to continue processing while the
  1347. operation completes. The event (or File handle if hEvent == NULL) will
  1348. be set to the not signalled state before ERROR_IO_PENDING is
  1349. returned. The event will be set to the signalled state upon completion
  1350. of the request. GetOverlappedResult is used to determine the result
  1351. when ERROR_IO_PENDING is returned.
  1352. Return Value:
  1353. TRUE -- The operation was successful.
  1354. FALSE -- The operation failed. Extended error status is available using
  1355. EtwpGetLastError.
  1356. --*/
  1357. {
  1358. NTSTATUS Status;
  1359. BOOLEAN DevIoCtl;
  1360. if ( dwIoControlCode >> 16 == FILE_DEVICE_FILE_SYSTEM ) {
  1361. DevIoCtl = FALSE;
  1362. }
  1363. else {
  1364. DevIoCtl = TRUE;
  1365. }
  1366. if ( ARGUMENT_PRESENT( lpOverlapped ) ) {
  1367. lpOverlapped->Internal = (DWORD)STATUS_PENDING;
  1368. if ( DevIoCtl ) {
  1369. Status = NtDeviceIoControlFile(
  1370. hDevice,
  1371. lpOverlapped->hEvent,
  1372. NULL, // APC routine
  1373. (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped,
  1374. (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  1375. dwIoControlCode, // IoControlCode
  1376. lpInBuffer, // Buffer for data to the FS
  1377. nInBufferSize,
  1378. lpOutBuffer, // OutputBuffer for data from the FS
  1379. nOutBufferSize // OutputBuffer Length
  1380. );
  1381. }
  1382. else {
  1383. Status = NtFsControlFile(
  1384. hDevice,
  1385. lpOverlapped->hEvent,
  1386. NULL, // APC routine
  1387. (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped,
  1388. (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  1389. dwIoControlCode, // IoControlCode
  1390. lpInBuffer, // Buffer for data to the FS
  1391. nInBufferSize,
  1392. lpOutBuffer, // OutputBuffer for data from the FS
  1393. nOutBufferSize // OutputBuffer Length
  1394. );
  1395. }
  1396. // handle warning value STATUS_BUFFER_OVERFLOW somewhat correctly
  1397. if ( !NT_ERROR(Status) && ARGUMENT_PRESENT(lpBytesReturned) ) {
  1398. try {
  1399. *lpBytesReturned = 0;
  1400. *lpBytesReturned = (DWORD)lpOverlapped->InternalHigh;
  1401. }
  1402. except(EXCEPTION_EXECUTE_HANDLER) {
  1403. }
  1404. }
  1405. if ( NT_SUCCESS(Status) && Status != STATUS_PENDING) {
  1406. return TRUE;
  1407. }
  1408. else {
  1409. EtwpBaseSetLastNTError(Status);
  1410. return FALSE;
  1411. }
  1412. }
  1413. else
  1414. {
  1415. IO_STATUS_BLOCK Iosb;
  1416. if (!(ARGUMENT_PRESENT(lpBytesReturned) ) ) {
  1417. EtwpSetDosError(ERROR_INVALID_PARAMETER);
  1418. return FALSE;
  1419. }
  1420. if ( DevIoCtl ) {
  1421. Status = NtDeviceIoControlFile(
  1422. hDevice,
  1423. NULL,
  1424. NULL, // APC routine
  1425. NULL, // APC Context
  1426. &Iosb,
  1427. dwIoControlCode, // IoControlCode
  1428. lpInBuffer, // Buffer for data to the FS
  1429. nInBufferSize,
  1430. lpOutBuffer, // OutputBuffer for data from the FS
  1431. nOutBufferSize // OutputBuffer Length
  1432. );
  1433. }
  1434. else {
  1435. Status = NtFsControlFile(
  1436. hDevice,
  1437. NULL,
  1438. NULL, // APC routine
  1439. NULL, // APC Context
  1440. &Iosb,
  1441. dwIoControlCode, // IoControlCode
  1442. lpInBuffer, // Buffer for data to the FS
  1443. nInBufferSize,
  1444. lpOutBuffer, // OutputBuffer for data from the FS
  1445. nOutBufferSize // OutputBuffer Length
  1446. );
  1447. }
  1448. if ( Status == STATUS_PENDING) {
  1449. // Operation must complete before return & Iosb destroyed
  1450. Status = NtWaitForSingleObject( hDevice, FALSE, NULL );
  1451. if ( NT_SUCCESS(Status)) {
  1452. Status = Iosb.Status;
  1453. }
  1454. }
  1455. if ( NT_SUCCESS(Status) ) {
  1456. *lpBytesReturned = (DWORD)Iosb.Information;
  1457. return TRUE;
  1458. }
  1459. else {
  1460. // handle warning value STATUS_BUFFER_OVERFLOW somewhat correctly
  1461. if ( !NT_ERROR(Status) ) {
  1462. *lpBytesReturned = (DWORD)Iosb.Information;
  1463. }
  1464. EtwpBaseSetLastNTError(Status);
  1465. return FALSE;
  1466. }
  1467. }
  1468. }
  1469. BOOL
  1470. WINAPI
  1471. EtwpCancelIo(
  1472. HANDLE hFile
  1473. )
  1474. /*++
  1475. Routine Description:
  1476. This routine cancels all of the outstanding I/O for the specified handle
  1477. for the specified file.
  1478. Arguments:
  1479. hFile - Supplies the handle to the file whose pending I/O is to be
  1480. canceled.
  1481. Return Value:
  1482. TRUE -- The operation was successful.
  1483. FALSE -- The operation failed. Extended error status is available using
  1484. EtwpGetLastError.
  1485. --*/
  1486. {
  1487. NTSTATUS Status;
  1488. IO_STATUS_BLOCK IoStatusBlock;
  1489. //
  1490. // Simply cancel the I/O for the specified file.
  1491. //
  1492. Status = NtCancelIoFile(hFile, &IoStatusBlock);
  1493. if ( NT_SUCCESS(Status) ) {
  1494. return TRUE;
  1495. }
  1496. else {
  1497. EtwpBaseSetLastNTError(Status);
  1498. return FALSE;
  1499. }
  1500. }
  1501. BOOL
  1502. EtwpSetEvent(
  1503. HANDLE hEvent
  1504. )
  1505. /*++
  1506. Routine Description:
  1507. An event can be set to the signaled state (TRUE) with the SetEvent
  1508. function.
  1509. Setting the event causes the event to attain a state of Signaled,
  1510. which releases all currently waiting threads (for manual reset
  1511. events), or a single waiting thread (for automatic reset events).
  1512. Arguments:
  1513. hEvent - Supplies an open handle to an event object. The
  1514. handle must have EVENT_MODIFY_STATE access to the event.
  1515. Return Value:
  1516. TRUE - The operation was successful
  1517. FALSE/NULL - The operation failed. Extended error status is available
  1518. using EtwpGetLastError.
  1519. --*/
  1520. {
  1521. NTSTATUS Status;
  1522. Status = NtSetEvent(hEvent,NULL);
  1523. if ( NT_SUCCESS(Status) ) {
  1524. return TRUE;
  1525. }
  1526. else {
  1527. EtwpBaseSetLastNTError(Status);
  1528. return FALSE;
  1529. }
  1530. }
  1531. DWORD
  1532. APIENTRY
  1533. EtwpWaitForMultipleObjectsEx(
  1534. DWORD nCount,
  1535. CONST HANDLE *lpHandles,
  1536. BOOL bWaitAll,
  1537. DWORD dwMilliseconds,
  1538. BOOL bAlertable
  1539. )
  1540. /*++
  1541. Routine Description:
  1542. A wait operation on multiple waitable objects (up to
  1543. MAXIMUM_WAIT_OBJECTS) is accomplished with the
  1544. WaitForMultipleObjects function.
  1545. This API can be used to wait on any of the specified objects to
  1546. enter the signaled state, or all of the objects to enter the
  1547. signaled state.
  1548. If the bAlertable parameter is FALSE, the only way the wait
  1549. terminates is because the specified timeout period expires, or
  1550. because the specified objects entered the signaled state. If the
  1551. bAlertable parameter is TRUE, then the wait can return due to any one of
  1552. the above wait termination conditions, or because an I/O completion
  1553. callback terminated the wait early (return value of
  1554. WAIT_IO_COMPLETION).
  1555. Arguments:
  1556. nCount - A count of the number of objects that are to be waited on.
  1557. lpHandles - An array of object handles. Each handle must have
  1558. SYNCHRONIZE access to the associated object.
  1559. bWaitAll - A flag that supplies the wait type. A value of TRUE
  1560. indicates a "wait all". A value of false indicates a "wait
  1561. any".
  1562. dwMilliseconds - A time-out value that specifies the relative time,
  1563. in milliseconds, over which the wait is to be completed. A
  1564. timeout value of 0 specified that the wait is to timeout
  1565. immediately. This allows an application to test an object to
  1566. determine if it is in the signaled state. A timeout value of
  1567. 0xffffffff specifies an infinite timeout period.
  1568. bAlertable - Supplies a flag that controls whether or not the
  1569. wait may terminate early due to an I/O completion callback.
  1570. A value of TRUE allows this API to complete early due to an I/O
  1571. completion callback. A value of FALSE will not allow I/O
  1572. completion callbacks to terminate this call early.
  1573. Return Value:
  1574. WAIT_TIME_OUT - indicates that the wait was terminated due to the
  1575. TimeOut conditions.
  1576. 0 to MAXIMUM_WAIT_OBJECTS-1, indicates, in the case of wait for any
  1577. object, the object number which satisfied the wait. In the case
  1578. of wait for all objects, the value only indicates that the wait
  1579. was completed successfully.
  1580. 0xffffffff - The wait terminated due to an error. EtwpGetLastError may be
  1581. used to get additional error information.
  1582. WAIT_ABANDONED_0 to (WAIT_ABANDONED_0)+(MAXIMUM_WAIT_OBJECTS - 1),
  1583. indicates, in the case of wait for any object, the object number
  1584. which satisfied the event, and that the object which satisfied
  1585. the event was abandoned. In the case of wait for all objects,
  1586. the value indicates that the wait was completed successfully and
  1587. at least one of the objects was abandoned.
  1588. WAIT_IO_COMPLETION - The wait terminated due to one or more I/O
  1589. completion callbacks.
  1590. --*/
  1591. {
  1592. NTSTATUS Status;
  1593. LARGE_INTEGER TimeOut;
  1594. PLARGE_INTEGER pTimeOut;
  1595. DWORD i;
  1596. LPHANDLE HandleArray;
  1597. HANDLE Handles[ 8 ];
  1598. PPEB Peb;
  1599. RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME Frame = { sizeof(Frame), RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER };
  1600. RtlActivateActivationContextUnsafeFast(&Frame, NULL); // make the process default activation context active so that APCs are delivered under it
  1601. __try {
  1602. if (nCount > 8) {
  1603. HandleArray = (LPHANDLE) RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TMP_TAG ), nCount*sizeof(HANDLE));
  1604. if (HandleArray == NULL) {
  1605. EtwpBaseSetLastNTError(STATUS_NO_MEMORY);
  1606. Status = (NTSTATUS)0xffffffff;
  1607. leave;
  1608. }
  1609. } else {
  1610. HandleArray = Handles;
  1611. }
  1612. RtlCopyMemory(HandleArray,(LPVOID)lpHandles,nCount*sizeof(HANDLE));
  1613. Peb = NtCurrentPeb();
  1614. for (i=0;i<nCount;i++) {
  1615. switch( HandleToUlong(HandleArray[i]) ) {
  1616. case STD_INPUT_HANDLE: HandleArray[i] = Peb->ProcessParameters->StandardInput;
  1617. break;
  1618. case STD_OUTPUT_HANDLE: HandleArray[i] = Peb->ProcessParameters->StandardOutput;
  1619. break;
  1620. case STD_ERROR_HANDLE: HandleArray[i] = Peb->ProcessParameters->StandardError;
  1621. break;
  1622. }
  1623. }
  1624. pTimeOut = EtwpBaseFormatTimeOut(&TimeOut,dwMilliseconds);
  1625. rewait:
  1626. Status = NtWaitForMultipleObjects(
  1627. nCount,
  1628. HandleArray,
  1629. bWaitAll ? WaitAll : WaitAny,
  1630. (BOOLEAN)bAlertable,
  1631. pTimeOut
  1632. );
  1633. if ( !NT_SUCCESS(Status) ) {
  1634. EtwpBaseSetLastNTError(Status);
  1635. Status = (NTSTATUS)0xffffffff;
  1636. }
  1637. else {
  1638. if ( bAlertable && Status == STATUS_ALERTED ) {
  1639. goto rewait;
  1640. }
  1641. }
  1642. if (HandleArray != Handles) {
  1643. RtlFreeHeap(RtlProcessHeap(), 0, HandleArray);
  1644. }
  1645. } __finally {
  1646. RtlDeactivateActivationContextUnsafeFast(&Frame);
  1647. }
  1648. return (DWORD)Status;
  1649. }
  1650. VOID
  1651. EtwpSleep(
  1652. DWORD dwMilliseconds
  1653. )
  1654. /*++
  1655. Routine Description:
  1656. The execution of the current thread can be delayed for a specified
  1657. interval of time with the Sleep function.
  1658. The Sleep function causes the current thread to enter a
  1659. waiting state until the specified interval of time has passed.
  1660. Arguments:
  1661. dwMilliseconds - A time-out value that specifies the relative time,
  1662. in milliseconds, over which the wait is to be completed. A
  1663. timeout value of 0 specified that the wait is to timeout
  1664. immediately. This allows an application to test an object to
  1665. determine if it is in the signaled state. A timeout value of -1
  1666. specifies an infinite timeout period.
  1667. Return Value:
  1668. None.
  1669. --*/
  1670. {
  1671. EtwpSleepEx(dwMilliseconds,FALSE);
  1672. }
  1673. DWORD
  1674. APIENTRY
  1675. EtwpSleepEx(
  1676. DWORD dwMilliseconds,
  1677. BOOL bAlertable
  1678. )
  1679. /*++
  1680. Routine Description:
  1681. The execution of the current thread can be delayed for a specified
  1682. interval of time with the SleepEx function.
  1683. The SleepEx function causes the current thread to enter a waiting
  1684. state until the specified interval of time has passed.
  1685. If the bAlertable parameter is FALSE, the only way the SleepEx
  1686. returns is when the specified time interval has passed. If the
  1687. bAlertable parameter is TRUE, then the SleepEx can return due to the
  1688. expiration of the time interval (return value of 0), or because an
  1689. I/O completion callback terminated the SleepEx early (return value
  1690. of WAIT_IO_COMPLETION).
  1691. Arguments:
  1692. dwMilliseconds - A time-out value that specifies the relative time,
  1693. in milliseconds, over which the wait is to be completed. A
  1694. timeout value of 0 specified that the wait is to timeout
  1695. immediately. A timeout value of -1 specifies an infinite
  1696. timeout period.
  1697. bAlertable - Supplies a flag that controls whether or not the
  1698. SleepEx may terminate early due to an I/O completion callback.
  1699. A value of TRUE allows this API to complete early due to an I/O
  1700. completion callback. A value of FALSE will not allow I/O
  1701. completion callbacks to terminate this call early.
  1702. Return Value:
  1703. 0 - The SleepEx terminated due to expiration of the time interval.
  1704. WAIT_IO_COMPLETION - The SleepEx terminated due to one or more I/O
  1705. completion callbacks.
  1706. --*/
  1707. {
  1708. LARGE_INTEGER TimeOut;
  1709. PLARGE_INTEGER pTimeOut;
  1710. NTSTATUS Status;
  1711. RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME Frame = { sizeof(Frame), RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER };
  1712. RtlActivateActivationContextUnsafeFast(&Frame, NULL); // make the process default activation context active so that APCs are delivered under it
  1713. __try {
  1714. pTimeOut = EtwpBaseFormatTimeOut(&TimeOut,dwMilliseconds);
  1715. if (pTimeOut == NULL) {
  1716. //
  1717. // If Sleep( -1 ) then delay for the longest possible integer
  1718. // relative to now.
  1719. //
  1720. TimeOut.LowPart = 0x0;
  1721. TimeOut.HighPart = 0x80000000;
  1722. pTimeOut = &TimeOut;
  1723. }
  1724. rewait:
  1725. Status = NtDelayExecution(
  1726. (BOOLEAN)bAlertable,
  1727. pTimeOut
  1728. );
  1729. if ( bAlertable && Status == STATUS_ALERTED ) {
  1730. goto rewait;
  1731. }
  1732. } __finally {
  1733. RtlDeactivateActivationContextUnsafeFast(&Frame);
  1734. }
  1735. return Status == STATUS_USER_APC ? WAIT_IO_COMPLETION : 0;
  1736. }
  1737. BOOL
  1738. APIENTRY
  1739. EtwpSetThreadPriority(
  1740. HANDLE hThread,
  1741. int nPriority
  1742. )
  1743. /*++
  1744. Routine Description:
  1745. The specified thread's priority can be set using SetThreadPriority.
  1746. A thread's priority may be set using SetThreadPriority. This call
  1747. allows the thread's relative execution importance to be communicated
  1748. to the system. The system normally schedules threads according to
  1749. their priority. The system is free to temporarily boost the
  1750. priority of a thread when signifigant events occur (e.g. keyboard
  1751. or mouse input...). Similarly, as a thread runs without blocking,
  1752. the system will decay its priority. The system will never decay the
  1753. priority below the value set by this call.
  1754. In the absence of system originated priority boosts, threads will be
  1755. scheduled in a round-robin fashion at each priority level from
  1756. THREAD_PRIORITY_TIME_CRITICAL to THREAD_PRIORITY_IDLE. Only when there
  1757. are no runnable threads at a higher level, will scheduling of
  1758. threads at a lower level take place.
  1759. All threads initially start at THREAD_PRIORITY_NORMAL.
  1760. If for some reason the thread needs more priority, it can be
  1761. switched to THREAD_PRIORITY_ABOVE_NORMAL or THREAD_PRIORITY_HIGHEST.
  1762. Switching to THREAD_PRIORITY_TIME_CRITICAL should only be done in extreme
  1763. situations. Since these threads are given the highes priority, they
  1764. should only run in short bursts. Running for long durations will
  1765. soak up the systems processing bandwidth starving threads at lower
  1766. levels.
  1767. If a thread needs to do low priority work, or should only run there
  1768. is nothing else to do, its priority should be set to
  1769. THREAD_PRIORITY_BELOW_NORMAL or THREAD_PRIORITY_LOWEST. For extreme
  1770. cases, THREAD_PRIORITY_IDLE can be used.
  1771. Care must be taken when manipulating priorites. If priorities are
  1772. used carelessly (every thread is set to THREAD_PRIORITY_TIME_CRITICAL),
  1773. the effects of priority modifications can produce undesireable
  1774. effects (e.g. starvation, no effect...).
  1775. Arguments:
  1776. hThread - Supplies a handle to the thread whose priority is to be
  1777. set. The handle must have been created with
  1778. THREAD_SET_INFORMATION access.
  1779. nPriority - Supplies the priority value for the thread. The
  1780. following five priority values (ordered from lowest priority to
  1781. highest priority) are allowed.
  1782. nPriority Values:
  1783. THREAD_PRIORITY_IDLE - The thread's priority should be set to
  1784. the lowest possible settable priority.
  1785. THREAD_PRIORITY_LOWEST - The thread's priority should be set to
  1786. the next lowest possible settable priority.
  1787. THREAD_PRIORITY_BELOW_NORMAL - The thread's priority should be
  1788. set to just below normal.
  1789. THREAD_PRIORITY_NORMAL - The thread's priority should be set to
  1790. the normal priority value. This is the value that all
  1791. threads begin execution at.
  1792. THREAD_PRIORITY_ABOVE_NORMAL - The thread's priority should be
  1793. set to just above normal priority.
  1794. THREAD_PRIORITY_HIGHEST - The thread's priority should be set to
  1795. the next highest possible settable priority.
  1796. THREAD_PRIORITY_TIME_CRITICAL - The thread's priority should be set
  1797. to the highest possible settable priority. This priority is
  1798. very likely to interfere with normal operation of the
  1799. system.
  1800. Return Value:
  1801. TRUE - The operation was successful
  1802. FALSE/NULL - The operation failed. Extended error status is available
  1803. using EtwpGetLastError.
  1804. --*/
  1805. {
  1806. NTSTATUS Status;
  1807. LONG BasePriority;
  1808. BasePriority = (LONG)nPriority;
  1809. //
  1810. // saturation is indicated by calling with a value of 16 or -16
  1811. //
  1812. if ( BasePriority == THREAD_PRIORITY_TIME_CRITICAL ) {
  1813. BasePriority = ((HIGH_PRIORITY + 1) / 2);
  1814. }
  1815. else if ( BasePriority == THREAD_PRIORITY_IDLE ) {
  1816. BasePriority = -((HIGH_PRIORITY + 1) / 2);
  1817. }
  1818. Status = NtSetInformationThread(
  1819. hThread,
  1820. ThreadBasePriority,
  1821. &BasePriority,
  1822. sizeof(BasePriority)
  1823. );
  1824. if ( !NT_SUCCESS(Status) ) {
  1825. EtwpBaseSetLastNTError(Status);
  1826. return FALSE;
  1827. }
  1828. return TRUE;
  1829. }
  1830. BOOL
  1831. EtwpDuplicateHandle(
  1832. HANDLE hSourceProcessHandle,
  1833. HANDLE hSourceHandle,
  1834. HANDLE hTargetProcessHandle,
  1835. LPHANDLE lpTargetHandle,
  1836. DWORD dwDesiredAccess,
  1837. BOOL bInheritHandle,
  1838. DWORD dwOptions
  1839. )
  1840. /*++
  1841. Routine Description:
  1842. A duplicate handle can be created with the DuplicateHandle function.
  1843. This is a generic function and operates on the following object
  1844. types:
  1845. - Process Object
  1846. - Thread Object
  1847. - Mutex Object
  1848. - Event Object
  1849. - Semaphore Object
  1850. - File Object
  1851. Please note that Module Objects are not in this list.
  1852. This function requires PROCESS_DUP_ACCESS to both the
  1853. SourceProcessHandle and the TargetProcessHandle. This function is
  1854. used to pass an object handle from one process to another. Once
  1855. this call is complete, the target process needs to be informed of
  1856. the value of the target handle. The target process can then operate
  1857. on the object using this handle value.
  1858. Arguments:
  1859. hSourceProcessHandle - An open handle to the process that contains the
  1860. handle to be duplicated. The handle must have been created with
  1861. PROCESS_DUP_HANDLE access to the process.
  1862. hSourceHandle - An open handle to any object that is valid in the
  1863. context of the source process.
  1864. hTargetProcessHandle - An open handle to the process that is to
  1865. receive the duplicated handle. The handle must have been
  1866. created with PROCESS_DUP_HANDLE access to the process.
  1867. lpTargetHandle - A pointer to a variable which receives the new handle
  1868. that points to the same object as SourceHandle does. This
  1869. handle value is valid in the context of the target process.
  1870. dwDesiredAccess - The access requested to for the new handle. This
  1871. parameter is ignored if the DUPLICATE_SAME_ACCESS option is
  1872. specified.
  1873. bInheritHandle - Supplies a flag that if TRUE, marks the target
  1874. handle as inheritable. If this is the case, then the target
  1875. handle will be inherited to new processes each time the target
  1876. process creates a new process using CreateProcess.
  1877. dwOptions - Specifies optional behaviors for the caller.
  1878. Options Flags:
  1879. DUPLICATE_CLOSE_SOURCE - The SourceHandle will be closed by
  1880. this service prior to returning to the caller. This occurs
  1881. regardless of any error status returned.
  1882. DUPLICATE_SAME_ACCESS - The DesiredAccess parameter is ignored
  1883. and instead the GrantedAccess associated with SourceHandle
  1884. is used as the DesiredAccess when creating the TargetHandle.
  1885. Return Value:
  1886. TRUE - The operation was successful.
  1887. FALSE/NULL - The operation failed. Extended error status is available
  1888. using EtwpGetLastError.
  1889. --*/
  1890. {
  1891. NTSTATUS Status;
  1892. PPEB Peb;
  1893. Peb = NtCurrentPeb();
  1894. switch( HandleToUlong(hSourceHandle) ) {
  1895. case STD_INPUT_HANDLE: hSourceHandle = Peb->ProcessParameters->StandardInput;
  1896. break;
  1897. case STD_OUTPUT_HANDLE: hSourceHandle = Peb->ProcessParameters->StandardOutput;
  1898. break;
  1899. case STD_ERROR_HANDLE: hSourceHandle = Peb->ProcessParameters->StandardError;
  1900. break;
  1901. }
  1902. Status = NtDuplicateObject(
  1903. hSourceProcessHandle,
  1904. hSourceHandle,
  1905. hTargetProcessHandle,
  1906. lpTargetHandle,
  1907. (ACCESS_MASK)dwDesiredAccess,
  1908. bInheritHandle ? OBJ_INHERIT : 0,
  1909. dwOptions
  1910. );
  1911. if ( NT_SUCCESS(Status) ) {
  1912. return TRUE;
  1913. }
  1914. else {
  1915. EtwpBaseSetLastNTError(Status);
  1916. return FALSE;
  1917. }
  1918. return FALSE;
  1919. }
  1920. HANDLE
  1921. APIENTRY
  1922. EtwpCreateThread(
  1923. LPSECURITY_ATTRIBUTES lpThreadAttributes,
  1924. DWORD dwStackSize,
  1925. LPTHREAD_START_ROUTINE lpStartAddress,
  1926. LPVOID lpParameter,
  1927. DWORD dwCreationFlags,
  1928. LPDWORD lpThreadId
  1929. )
  1930. {
  1931. HANDLE ThreadHandle;
  1932. //
  1933. // We changed the code from RtlCreateUserThread to RtlpStartThreadFunc
  1934. // to create WIN32 threads. When kernel32 loads it hands over the pointer
  1935. // of BaseCreateThreadPoolThread and assigns it to RtlpStartThreadFunc.
  1936. // So we can happily create WIN32 Thread using RtlpStartThreadFunc.
  1937. //
  1938. NTSTATUS st = RtlpStartThreadFunc(lpStartAddress,
  1939. lpParameter,
  1940. &ThreadHandle);
  1941. if(NT_SUCCESS(st)){
  1942. st = NtResumeThread(ThreadHandle,NULL);
  1943. if(NT_SUCCESS(st)){
  1944. return ThreadHandle;
  1945. } else {
  1946. NtTerminateThread(ThreadHandle,st);
  1947. NtClose(ThreadHandle);
  1948. }
  1949. }
  1950. return NULL;
  1951. }
  1952. /////////////////////////////////////////////////////////
  1953. /////////////////////////////////////////////////////////
  1954. // TLS FUNCTIONS
  1955. /////////////////////////////////////////////////////////
  1956. /////////////////////////////////////////////////////////
  1957. DWORD
  1958. EtwpTlsAlloc(
  1959. VOID
  1960. )
  1961. /*++
  1962. Routine Description:
  1963. A TLS index may be allocated using TlsAllocHelper. Win32 garuntees a
  1964. minimum number of TLS indexes are available in each process. The
  1965. constant TLS_MINIMUM_AVAILABLE defines the minimum number of
  1966. available indexes. This minimum is at least 64 for all Win32
  1967. systems.
  1968. Arguments:
  1969. None.
  1970. Return Value:
  1971. Not-0xffffffff - Returns a TLS index that may be used in a
  1972. subsequent call to TlsFreeHelper, TlsSetValueHelper, or TlsGetValueHelper. The
  1973. storage associated with the index is initialized to NULL.
  1974. 0xffffffff - The operation failed. Extended error status is available
  1975. using GetLastError.
  1976. --*/
  1977. {
  1978. PPEB Peb;
  1979. PTEB Teb;
  1980. DWORD Index;
  1981. Peb = NtCurrentPeb();
  1982. Teb = NtCurrentTeb();
  1983. RtlAcquirePebLock();
  1984. try {
  1985. Index = RtlFindClearBitsAndSet((PRTL_BITMAP)Peb->TlsBitmap,1,0);
  1986. if ( Index == 0xffffffff ) {
  1987. Index = RtlFindClearBitsAndSet((PRTL_BITMAP)Peb->TlsExpansionBitmap,1,0);
  1988. if ( Index == 0xffffffff ) {
  1989. EtwpSetLastError(RtlNtStatusToDosError(STATUS_NO_MEMORY));
  1990. }
  1991. else {
  1992. if ( !Teb->TlsExpansionSlots ) {
  1993. Teb->TlsExpansionSlots = RtlAllocateHeap(
  1994. RtlProcessHeap(),
  1995. MAKE_TAG( TMP_TAG ) | HEAP_ZERO_MEMORY,
  1996. TLS_EXPANSION_SLOTS * sizeof(PVOID)
  1997. );
  1998. if ( !Teb->TlsExpansionSlots ) {
  1999. RtlClearBits((PRTL_BITMAP)Peb->TlsExpansionBitmap,Index,1);
  2000. Index = 0xffffffff;
  2001. EtwpSetLastError(RtlNtStatusToDosError(STATUS_NO_MEMORY));
  2002. leave;
  2003. }
  2004. }
  2005. Teb->TlsExpansionSlots[Index] = NULL;
  2006. Index += TLS_MINIMUM_AVAILABLE;
  2007. }
  2008. }
  2009. else {
  2010. Teb->TlsSlots[Index] = NULL;
  2011. }
  2012. }
  2013. finally {
  2014. RtlReleasePebLock();
  2015. }
  2016. #if DBG
  2017. Index |= TLS_MASK;
  2018. #endif
  2019. return Index;
  2020. }
  2021. LPVOID
  2022. EtwpTlsGetValue(
  2023. DWORD dwTlsIndex
  2024. )
  2025. /*++
  2026. Routine Description:
  2027. This function is used to retrive the value in the TLS storage
  2028. associated with the specified index.
  2029. If the index is valid this function clears the value returned by
  2030. GetLastError(), and returns the value stored in the TLS slot
  2031. associated with the specified index. Otherwise a value of NULL is
  2032. returned with GetLastError updated appropriately.
  2033. It is expected, that DLLs will use TlsAllocHelper and TlsGetValueHelper as
  2034. follows:
  2035. - Upon DLL initialization, a TLS index will be allocated using
  2036. TlsAllocHelper. The DLL will then allocate some dynamic storage and
  2037. store its address in the TLS slot using TlsSetValueHelper. This
  2038. completes the per thread initialization for the initial thread
  2039. of the process. The TLS index is stored in instance data for
  2040. the DLL.
  2041. - Each time a new thread attaches to the DLL, the DLL will
  2042. allocate some dynamic storage and store its address in the TLS
  2043. slot using TlsSetValueHelper. This completes the per thread
  2044. initialization for the new thread.
  2045. - Each time an initialized thread makes a DLL call requiring the
  2046. TLS, the DLL will call TlsGetValueHelper to get the TLS data for the
  2047. thread.
  2048. Arguments:
  2049. dwTlsIndex - Supplies a TLS index allocated using TlsAllocHelper. The
  2050. index specifies which TLS slot is to be located. Translating a
  2051. TlsIndex does not prevent a TlsFreeHelper call from proceding.
  2052. Return Value:
  2053. NON-NULL - The function was successful. The value is the data stored
  2054. in the TLS slot associated with the specified index.
  2055. NULL - The operation failed, or the value associated with the
  2056. specified index was NULL. Extended error status is available
  2057. using GetLastError. If this returns non-zero, the index was
  2058. invalid.
  2059. --*/
  2060. {
  2061. PTEB Teb;
  2062. LPVOID *Slot;
  2063. #if DBG
  2064. // See if the Index passed in is from TlsAllocHelper or random goo...
  2065. ASSERTMSG( "BASEDLL: Invalid TlsIndex passed to TlsGetValueHelper\n", (dwTlsIndex & TLS_MASK));
  2066. dwTlsIndex &= ~TLS_MASK;
  2067. #endif
  2068. Teb = NtCurrentTeb();
  2069. if ( dwTlsIndex < TLS_MINIMUM_AVAILABLE ) {
  2070. Slot = &Teb->TlsSlots[dwTlsIndex];
  2071. Teb->LastErrorValue = 0;
  2072. return *Slot;
  2073. }
  2074. else {
  2075. if ( dwTlsIndex >= TLS_MINIMUM_AVAILABLE+TLS_EXPANSION_SLOTS ) {
  2076. EtwpSetLastError(RtlNtStatusToDosError(STATUS_INVALID_PARAMETER));
  2077. return NULL;
  2078. }
  2079. else {
  2080. Teb->LastErrorValue = 0;
  2081. if ( Teb->TlsExpansionSlots ) {
  2082. return Teb->TlsExpansionSlots[dwTlsIndex-TLS_MINIMUM_AVAILABLE];
  2083. }
  2084. else {
  2085. return NULL;
  2086. }
  2087. }
  2088. }
  2089. }
  2090. BOOL
  2091. EtwpTlsSetValue(
  2092. DWORD dwTlsIndex,
  2093. LPVOID lpTlsValue
  2094. )
  2095. /*++
  2096. Routine Description:
  2097. This function is used to store a value in the TLS storage associated
  2098. with the specified index.
  2099. If the index is valid this function stores the value and returns
  2100. TRUE. Otherwise a value of FALSE is returned.
  2101. It is expected, that DLLs will use TlsAllocHelper and TlsSetValueHelper as
  2102. follows:
  2103. - Upon DLL initialization, a TLS index will be allocated using
  2104. TlsAllocHelper. The DLL will then allocate some dynamic storage and
  2105. store its address in the TLS slot using TlsSetValueHelper. This
  2106. completes the per thread initialization for the initial thread
  2107. of the process. The TLS index is stored in instance data for
  2108. the DLL.
  2109. - Each time a new thread attaches to the DLL, the DLL will
  2110. allocate some dynamic storage and store its address in the TLS
  2111. slot using TlsSetValueHelper. This completes the per thread
  2112. initialization for the new thread.
  2113. - Each time an initialized thread makes a DLL call requiring the
  2114. TLS, the DLL will call TlsGetValueHelper to get the TLS data for the
  2115. thread.
  2116. Arguments:
  2117. dwTlsIndex - Supplies a TLS index allocated using TlsAllocHelper. The
  2118. index specifies which TLS slot is to be located. Translating a
  2119. TlsIndex does not prevent a TlsFreeHelper call from proceding.
  2120. lpTlsValue - Supplies the value to be stored in the TLS Slot.
  2121. Return Value:
  2122. TRUE - The function was successful. The value lpTlsValue was
  2123. stored.
  2124. FALSE - The operation failed. Extended error status is available
  2125. using GetLastError.
  2126. --*/
  2127. {
  2128. PTEB Teb;
  2129. #if DBG
  2130. // See if the Index passed in is from TlsAllocHelper or random goo...
  2131. ASSERTMSG( "BASEDLL: Invalid TlsIndex passed to TlsSetValueHelper\n", (dwTlsIndex & TLS_MASK));
  2132. dwTlsIndex &= ~TLS_MASK;
  2133. #endif
  2134. Teb = NtCurrentTeb();
  2135. if ( dwTlsIndex >= TLS_MINIMUM_AVAILABLE ) {
  2136. dwTlsIndex -= TLS_MINIMUM_AVAILABLE;
  2137. if ( dwTlsIndex < TLS_EXPANSION_SLOTS ) {
  2138. if ( !Teb->TlsExpansionSlots ) {
  2139. RtlAcquirePebLock();
  2140. if ( !Teb->TlsExpansionSlots ) {
  2141. Teb->TlsExpansionSlots = RtlAllocateHeap(
  2142. RtlProcessHeap(),
  2143. MAKE_TAG( TMP_TAG ) | HEAP_ZERO_MEMORY,
  2144. TLS_EXPANSION_SLOTS * sizeof(PVOID)
  2145. );
  2146. if ( !Teb->TlsExpansionSlots ) {
  2147. RtlReleasePebLock();
  2148. EtwpSetLastError(RtlNtStatusToDosError(STATUS_NO_MEMORY));
  2149. return FALSE;
  2150. }
  2151. }
  2152. RtlReleasePebLock();
  2153. }
  2154. Teb->TlsExpansionSlots[dwTlsIndex] = lpTlsValue;
  2155. }
  2156. else {
  2157. EtwpSetLastError(RtlNtStatusToDosError(STATUS_INVALID_PARAMETER));
  2158. return FALSE;
  2159. }
  2160. }
  2161. else {
  2162. Teb->TlsSlots[dwTlsIndex] = lpTlsValue;
  2163. }
  2164. return TRUE;
  2165. }
  2166. BOOL
  2167. EtwpTlsFree(
  2168. DWORD dwTlsIndex
  2169. )
  2170. /*++
  2171. Routine Description:
  2172. A valid TLS index may be free'd using TlsFreeHelper.
  2173. Arguments:
  2174. dwTlsIndex - Supplies a TLS index allocated using TlsAllocHelper. If the
  2175. index is a valid index, it is released by this call and is made
  2176. available for reuse. DLLs should be carefull to release any
  2177. per-thread data pointed to by all of their threads TLS slots
  2178. before calling this function. It is expected that DLLs will
  2179. only call this function (if at ALL) during their process detach
  2180. routine.
  2181. Return Value:
  2182. TRUE - The operation was successful. Calling TlsTranslateIndex with
  2183. this index will fail. TlsAllocHelper is free to reallocate this
  2184. index.
  2185. FALSE - The operation failed. Extended error status is available
  2186. using GetLastError.
  2187. --*/
  2188. {
  2189. PPEB Peb;
  2190. BOOLEAN ValidIndex;
  2191. PRTL_BITMAP TlsBitmap;
  2192. NTSTATUS Status;
  2193. DWORD Index2;
  2194. #if DBG
  2195. // See if the Index passed in is from TlsAllocHelper or random goo...
  2196. ASSERTMSG( "BASEDLL: Invalid TlsIndex passed to TlsFreeHelper\n", (dwTlsIndex & TLS_MASK));
  2197. dwTlsIndex &= ~TLS_MASK;
  2198. #endif
  2199. Peb = NtCurrentPeb();
  2200. RtlAcquirePebLock();
  2201. try {
  2202. if ( dwTlsIndex >= TLS_MINIMUM_AVAILABLE ) {
  2203. Index2 = dwTlsIndex - TLS_MINIMUM_AVAILABLE;
  2204. if ( Index2 >= TLS_EXPANSION_SLOTS ) {
  2205. ValidIndex = FALSE;
  2206. }
  2207. else {
  2208. TlsBitmap = (PRTL_BITMAP)Peb->TlsExpansionBitmap;
  2209. ValidIndex = RtlAreBitsSet(TlsBitmap,Index2,1);
  2210. }
  2211. }
  2212. else {
  2213. TlsBitmap = (PRTL_BITMAP)Peb->TlsBitmap;
  2214. Index2 = dwTlsIndex;
  2215. ValidIndex = RtlAreBitsSet(TlsBitmap,Index2,1);
  2216. }
  2217. if ( ValidIndex ) {
  2218. Status = NtSetInformationThread(
  2219. NtCurrentThread(),
  2220. ThreadZeroTlsCell,
  2221. &dwTlsIndex,
  2222. sizeof(dwTlsIndex)
  2223. );
  2224. if ( !NT_SUCCESS(Status) ) {
  2225. EtwpSetLastError(RtlNtStatusToDosError(STATUS_INVALID_PARAMETER));
  2226. ValidIndex = FALSE;
  2227. leave;
  2228. }
  2229. RtlClearBits(TlsBitmap,Index2,1);
  2230. }
  2231. else {
  2232. EtwpSetLastError(RtlNtStatusToDosError(STATUS_INVALID_PARAMETER));
  2233. }
  2234. }
  2235. finally {
  2236. RtlReleasePebLock();
  2237. }
  2238. return ValidIndex;
  2239. }
  2240. BOOL
  2241. EtwpBasep8BitStringToDynamicUnicodeString(
  2242. OUT PUNICODE_STRING UnicodeString,
  2243. IN LPCSTR lpSourceString
  2244. )
  2245. /*++
  2246. Routine Description:
  2247. Captures and converts a 8-bit (OEM or ANSI) string into a heap-allocated
  2248. UNICODE string
  2249. Arguments:
  2250. UnicodeString - location where UNICODE_STRING is stored
  2251. lpSourceString - string in OEM or ANSI
  2252. Return Value:
  2253. TRUE if string is correctly stored, FALSE if an error occurred. In the
  2254. error case, the last error is correctly set.
  2255. --*/
  2256. {
  2257. ANSI_STRING AnsiString;
  2258. NTSTATUS Status;
  2259. //
  2260. // Convert input into dynamic unicode string
  2261. //
  2262. RtlInitString( &AnsiString, lpSourceString );
  2263. Status = RtlAnsiStringToUnicodeString( UnicodeString, &AnsiString, TRUE );
  2264. //
  2265. // If we couldn't do this, fail
  2266. //
  2267. if (!NT_SUCCESS( Status )){
  2268. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  2269. EtwpSetLastError( ERROR_FILENAME_EXCED_RANGE );
  2270. } else {
  2271. EtwpBaseSetLastNTError( Status );
  2272. }
  2273. return FALSE;
  2274. }
  2275. return TRUE;
  2276. }
  2277. DWORD
  2278. APIENTRY
  2279. EtwpGetFullPathNameA(
  2280. LPCSTR lpFileName,
  2281. DWORD nBufferLength,
  2282. LPSTR lpBuffer,
  2283. LPSTR *lpFilePart
  2284. )
  2285. /*++
  2286. Routine Description:
  2287. ANSI thunk to GetFullPathNameW
  2288. --*/
  2289. {
  2290. NTSTATUS Status;
  2291. ULONG UnicodeLength;
  2292. UNICODE_STRING UnicodeString;
  2293. UNICODE_STRING UnicodeResult;
  2294. ANSI_STRING AnsiResult;
  2295. PWSTR Ubuff;
  2296. PWSTR FilePart=NULL;
  2297. PWSTR *FilePartPtr;
  2298. INT PrefixLength = 0;
  2299. if ( ARGUMENT_PRESENT(lpFilePart) ) {
  2300. FilePartPtr = &FilePart;
  2301. }
  2302. else {
  2303. FilePartPtr = NULL;
  2304. }
  2305. if (!EtwpBasep8BitStringToDynamicUnicodeString( &UnicodeString, lpFileName )) {
  2306. return 0;
  2307. }
  2308. Ubuff = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TMP_TAG ), (MAX_PATH<<1) + sizeof(UNICODE_NULL));
  2309. if ( !Ubuff ) {
  2310. RtlFreeUnicodeString(&UnicodeString);
  2311. EtwpBaseSetLastNTError(STATUS_NO_MEMORY);
  2312. return 0;
  2313. }
  2314. UnicodeLength = RtlGetFullPathName_U(
  2315. UnicodeString.Buffer,
  2316. (MAX_PATH<<1),
  2317. Ubuff,
  2318. FilePartPtr
  2319. );
  2320. //
  2321. // UnicodeLength contains the byte count of unicode string.
  2322. // Original code does "UnicodeLength / sizeof(WCHAR)" to get
  2323. // the size of corresponding ansi string.
  2324. // This is correct in SBCS environment. However in DBCS environment,
  2325. // it's definitely WRONG.
  2326. //
  2327. if ( UnicodeLength <= ((MAX_PATH * sizeof(WCHAR) + sizeof(UNICODE_NULL))) ) {
  2328. Status = RtlUnicodeToMultiByteSize(&UnicodeLength, Ubuff, UnicodeLength);
  2329. //
  2330. // At this point, UnicodeLength variable contains
  2331. // Ansi based byte length.
  2332. //
  2333. if ( NT_SUCCESS(Status) ) {
  2334. if ( UnicodeLength && ARGUMENT_PRESENT(lpFilePart) && FilePart != NULL ) {
  2335. INT UnicodePrefixLength;
  2336. UnicodePrefixLength = (INT)(FilePart - Ubuff) * sizeof(WCHAR);
  2337. Status = RtlUnicodeToMultiByteSize( &PrefixLength,
  2338. Ubuff,
  2339. UnicodePrefixLength );
  2340. //
  2341. // At this point, PrefixLength variable contains
  2342. // Ansi based byte length.
  2343. //
  2344. if ( !NT_SUCCESS(Status) ) {
  2345. EtwpBaseSetLastNTError(Status);
  2346. UnicodeLength = 0;
  2347. }
  2348. }
  2349. } else {
  2350. EtwpBaseSetLastNTError(Status);
  2351. UnicodeLength = 0;
  2352. }
  2353. } else {
  2354. //
  2355. // we exceed the MAX_PATH limit. we should log the error and
  2356. // return zero. however US code returns the byte count of
  2357. // buffer required and doesn't log any error.
  2358. //
  2359. UnicodeLength = 0;
  2360. }
  2361. if ( UnicodeLength && UnicodeLength < nBufferLength ) {
  2362. RtlInitUnicodeString(&UnicodeResult,Ubuff);
  2363. Status = RtlUnicodeStringToAnsiString(&AnsiResult,&UnicodeResult,TRUE);
  2364. if ( NT_SUCCESS(Status) ) {
  2365. RtlMoveMemory(lpBuffer,AnsiResult.Buffer,UnicodeLength+1);
  2366. RtlFreeAnsiString(&AnsiResult);
  2367. if ( ARGUMENT_PRESENT(lpFilePart) ) {
  2368. if ( FilePart == NULL ) {
  2369. *lpFilePart = NULL;
  2370. }
  2371. else {
  2372. *lpFilePart = lpBuffer + PrefixLength;
  2373. }
  2374. }
  2375. }
  2376. else {
  2377. EtwpBaseSetLastNTError(Status);
  2378. UnicodeLength = 0;
  2379. }
  2380. }
  2381. else {
  2382. if ( UnicodeLength ) {
  2383. UnicodeLength++;
  2384. }
  2385. }
  2386. RtlFreeUnicodeString(&UnicodeString);
  2387. RtlFreeHeap(RtlProcessHeap(), 0,Ubuff);
  2388. return (DWORD)UnicodeLength;
  2389. }
  2390. DWORD
  2391. APIENTRY
  2392. EtwpGetFullPathNameW(
  2393. LPCWSTR lpFileName,
  2394. DWORD nBufferLength,
  2395. LPWSTR lpBuffer,
  2396. LPWSTR *lpFilePart
  2397. )
  2398. /*++
  2399. Routine Description:
  2400. This function is used to return the fully qualified path name
  2401. corresponding to the specified file name.
  2402. This function is used to return a fully qualified pathname
  2403. corresponding to the specified filename. It does this by merging
  2404. the current drive and directory together with the specified file
  2405. name. In addition to this, it calculates the address of the file
  2406. name portion of the fully qualified pathname.
  2407. Arguments:
  2408. lpFileName - Supplies the file name of the file whose fully
  2409. qualified pathname is to be returned.
  2410. nBufferLength - Supplies the length in number of wide characters of the
  2411. buffer that is to receive the fully qualified path.
  2412. lpBuffer - Returns the fully qualified pathname corresponding to the
  2413. specified file.
  2414. lpFilePart - Returns the address of the last component of the fully
  2415. qualified pathname.
  2416. Return Value:
  2417. The return value is the length of the string(in number of wide characters)
  2418. copied to lpBuffer, not including the terminating null character.
  2419. If the return value is greater than nBufferLength, the return value is the
  2420. size of the buffer required to hold the pathname. The return value is zero
  2421. if the function failed.
  2422. --*/
  2423. {
  2424. return (DWORD) RtlGetFullPathName_U(
  2425. lpFileName,
  2426. nBufferLength*2,
  2427. lpBuffer,
  2428. lpFilePart
  2429. )/2;
  2430. }
  2431. BOOL
  2432. EtwpResetEvent(
  2433. HANDLE hEvent
  2434. )
  2435. /*++
  2436. Routine Description:
  2437. The state of an event is set to the Not-Signaled state (FALSE) using
  2438. the ClearEvent function.
  2439. Once the event attains a state of Not-Signaled, any threads which
  2440. wait on the event block, awaiting the event to become Signaled. The
  2441. reset event service sets the event count to zero for the state of
  2442. the event.
  2443. Arguments:
  2444. hEvent - Supplies an open handle to an event object. The
  2445. handle must have EVENT_MODIFY_STATE access to the event.
  2446. Return Value:
  2447. TRUE - The operation was successful
  2448. FALSE/NULL - The operation failed. Extended error status is available
  2449. using GetLastError.
  2450. --*/
  2451. {
  2452. NTSTATUS Status;
  2453. Status = NtClearEvent(hEvent);
  2454. if ( NT_SUCCESS(Status) ) {
  2455. return TRUE;
  2456. }
  2457. else {
  2458. EtwpBaseSetLastNTError(Status);
  2459. return FALSE;
  2460. }
  2461. }
  2462. BOOL
  2463. WINAPI
  2464. EtwpGetDiskFreeSpaceExW(
  2465. LPCWSTR lpDirectoryName,
  2466. PULARGE_INTEGER lpFreeBytesAvailableToCaller,
  2467. PULARGE_INTEGER lpTotalNumberOfBytes,
  2468. PULARGE_INTEGER lpTotalNumberOfFreeBytes
  2469. )
  2470. {
  2471. NTSTATUS Status;
  2472. OBJECT_ATTRIBUTES Obja;
  2473. HANDLE Handle;
  2474. UNICODE_STRING FileName;
  2475. IO_STATUS_BLOCK IoStatusBlock;
  2476. BOOLEAN TranslationStatus;
  2477. PVOID FreeBuffer;
  2478. union {
  2479. FILE_FS_SIZE_INFORMATION Normal;
  2480. FILE_FS_FULL_SIZE_INFORMATION Full;
  2481. } SizeInfo;
  2482. WCHAR DefaultPath[2];
  2483. ULARGE_INTEGER BytesPerAllocationUnit;
  2484. ULARGE_INTEGER FreeBytesAvailableToCaller;
  2485. ULARGE_INTEGER TotalNumberOfBytes;
  2486. DefaultPath[0] = (WCHAR)'\\';
  2487. DefaultPath[1] = UNICODE_NULL;
  2488. TranslationStatus = RtlDosPathNameToNtPathName_U(
  2489. ARGUMENT_PRESENT(lpDirectoryName) ? lpDirectoryName : DefaultPath,
  2490. &FileName,
  2491. NULL,
  2492. NULL
  2493. );
  2494. if ( !TranslationStatus ) {
  2495. EtwpSetLastError(ERROR_PATH_NOT_FOUND);
  2496. return FALSE;
  2497. }
  2498. FreeBuffer = FileName.Buffer;
  2499. InitializeObjectAttributes(
  2500. &Obja,
  2501. &FileName,
  2502. OBJ_CASE_INSENSITIVE,
  2503. NULL,
  2504. NULL
  2505. );
  2506. //
  2507. // Open the file
  2508. //
  2509. Status = NtOpenFile(
  2510. &Handle,
  2511. (ACCESS_MASK)FILE_LIST_DIRECTORY | SYNCHRONIZE,
  2512. &Obja,
  2513. &IoStatusBlock,
  2514. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2515. FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE | FILE_OPEN_FOR_FREE_SPACE_QUERY
  2516. );
  2517. if ( !NT_SUCCESS(Status) ) {
  2518. EtwpBaseSetLastNTError(Status);
  2519. if ( EtwpGetLastError() == ERROR_FILE_NOT_FOUND ) {
  2520. EtwpSetLastError(ERROR_PATH_NOT_FOUND);
  2521. }
  2522. RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
  2523. return FALSE;
  2524. }
  2525. RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
  2526. //
  2527. // If the caller wants the volume total then try to get a full
  2528. // file size.
  2529. //
  2530. if ( ARGUMENT_PRESENT(lpTotalNumberOfFreeBytes) ) {
  2531. Status = NtQueryVolumeInformationFile(
  2532. Handle,
  2533. &IoStatusBlock,
  2534. &SizeInfo,
  2535. sizeof(SizeInfo.Full),
  2536. FileFsFullSizeInformation
  2537. );
  2538. if ( NT_SUCCESS(Status) ) {
  2539. NtClose(Handle);
  2540. BytesPerAllocationUnit.QuadPart =
  2541. SizeInfo.Full.BytesPerSector * SizeInfo.Full.SectorsPerAllocationUnit;
  2542. if ( ARGUMENT_PRESENT(lpFreeBytesAvailableToCaller) ) {
  2543. lpFreeBytesAvailableToCaller->QuadPart =
  2544. BytesPerAllocationUnit.QuadPart *
  2545. SizeInfo.Full.CallerAvailableAllocationUnits.QuadPart;
  2546. }
  2547. if ( ARGUMENT_PRESENT(lpTotalNumberOfBytes) ) {
  2548. lpTotalNumberOfBytes->QuadPart =
  2549. BytesPerAllocationUnit.QuadPart * SizeInfo.Full.TotalAllocationUnits.QuadPart;
  2550. }
  2551. lpTotalNumberOfFreeBytes->QuadPart =
  2552. BytesPerAllocationUnit.QuadPart *
  2553. SizeInfo.Full.ActualAvailableAllocationUnits.QuadPart;
  2554. return TRUE;
  2555. }
  2556. }
  2557. //
  2558. // Determine the size parameters of the volume.
  2559. //
  2560. Status = NtQueryVolumeInformationFile(
  2561. Handle,
  2562. &IoStatusBlock,
  2563. &SizeInfo,
  2564. sizeof(SizeInfo.Normal),
  2565. FileFsSizeInformation
  2566. );
  2567. NtClose(Handle);
  2568. if ( !NT_SUCCESS(Status) ) {
  2569. EtwpBaseSetLastNTError(Status);
  2570. return FALSE;
  2571. }
  2572. BytesPerAllocationUnit.QuadPart =
  2573. SizeInfo.Normal.BytesPerSector * SizeInfo.Normal.SectorsPerAllocationUnit;
  2574. FreeBytesAvailableToCaller.QuadPart =
  2575. BytesPerAllocationUnit.QuadPart * SizeInfo.Normal.AvailableAllocationUnits.QuadPart;
  2576. TotalNumberOfBytes.QuadPart =
  2577. BytesPerAllocationUnit.QuadPart * SizeInfo.Normal.TotalAllocationUnits.QuadPart;
  2578. if ( ARGUMENT_PRESENT(lpFreeBytesAvailableToCaller) ) {
  2579. lpFreeBytesAvailableToCaller->QuadPart = FreeBytesAvailableToCaller.QuadPart;
  2580. }
  2581. if ( ARGUMENT_PRESENT(lpTotalNumberOfBytes) ) {
  2582. lpTotalNumberOfBytes->QuadPart = TotalNumberOfBytes.QuadPart;
  2583. }
  2584. if ( ARGUMENT_PRESENT(lpTotalNumberOfFreeBytes) ) {
  2585. lpTotalNumberOfFreeBytes->QuadPart = FreeBytesAvailableToCaller.QuadPart;
  2586. }
  2587. return TRUE;
  2588. }
  2589. BOOL
  2590. APIENTRY
  2591. EtwpGetFileAttributesExW(
  2592. LPCWSTR lpFileName,
  2593. GET_FILEEX_INFO_LEVELS fInfoLevelId,
  2594. LPVOID lpFileInformation
  2595. )
  2596. /*++
  2597. Routine Description:
  2598. The main attributes of a file can be obtained using GetFileAttributesEx.
  2599. Arguments:
  2600. lpFileName - Supplies the file name of the file whose attributes are to
  2601. be set.
  2602. fInfoLevelId - Supplies the info level indicating the information to be
  2603. returned about the file.
  2604. lpFileInformation - Supplies a buffer to receive the specified information
  2605. about the file.
  2606. Return Value:
  2607. TRUE - The operation was successful.
  2608. FALSE/NULL - The operation failed. Extended error status is available
  2609. using GetLastError.
  2610. --*/
  2611. {
  2612. NTSTATUS Status;
  2613. OBJECT_ATTRIBUTES Obja;
  2614. UNICODE_STRING FileName;
  2615. FILE_NETWORK_OPEN_INFORMATION NetworkInfo;
  2616. LPWIN32_FILE_ATTRIBUTE_DATA AttributeData;
  2617. BOOLEAN TranslationStatus;
  2618. RTL_RELATIVE_NAME_U RelativeName;
  2619. PVOID FreeBuffer;
  2620. //
  2621. // Check the parameters. Note that for now there is only one info level,
  2622. // so there's no special code here to determine what to do.
  2623. //
  2624. if ( fInfoLevelId >= GetFileExMaxInfoLevel || fInfoLevelId < GetFileExInfoStandard ) {
  2625. EtwpSetLastError(ERROR_INVALID_PARAMETER);
  2626. return FALSE;
  2627. }
  2628. TranslationStatus = RtlDosPathNameToRelativeNtPathName_U(
  2629. lpFileName,
  2630. &FileName,
  2631. NULL,
  2632. &RelativeName
  2633. );
  2634. if ( !TranslationStatus ) {
  2635. EtwpSetLastError(ERROR_PATH_NOT_FOUND);
  2636. return FALSE;
  2637. }
  2638. FreeBuffer = FileName.Buffer;
  2639. if ( RelativeName.RelativeName.Length ) {
  2640. FileName = RelativeName.RelativeName;
  2641. }
  2642. else {
  2643. RelativeName.ContainingDirectory = NULL;
  2644. }
  2645. InitializeObjectAttributes(
  2646. &Obja,
  2647. &FileName,
  2648. OBJ_CASE_INSENSITIVE,
  2649. RelativeName.ContainingDirectory,
  2650. NULL
  2651. );
  2652. //
  2653. // Query the information about the file using the path-based NT service.
  2654. //
  2655. Status = NtQueryFullAttributesFile( &Obja, &NetworkInfo );
  2656. RtlReleaseRelativeName(&RelativeName);
  2657. RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
  2658. if ( NT_SUCCESS(Status) ) {
  2659. AttributeData = (LPWIN32_FILE_ATTRIBUTE_DATA)lpFileInformation;
  2660. AttributeData->dwFileAttributes = NetworkInfo.FileAttributes;
  2661. AttributeData->ftCreationTime = *(PFILETIME)&NetworkInfo.CreationTime;
  2662. AttributeData->ftLastAccessTime = *(PFILETIME)&NetworkInfo.LastAccessTime;
  2663. AttributeData->ftLastWriteTime = *(PFILETIME)&NetworkInfo.LastWriteTime;
  2664. AttributeData->nFileSizeHigh = NetworkInfo.EndOfFile.HighPart;
  2665. AttributeData->nFileSizeLow = (DWORD)NetworkInfo.EndOfFile.LowPart;
  2666. return TRUE;
  2667. }
  2668. else {
  2669. EtwpBaseSetLastNTError(Status);
  2670. return FALSE;
  2671. }
  2672. }
  2673. BOOL
  2674. APIENTRY
  2675. EtwpDeleteFileW(
  2676. LPCWSTR lpFileName
  2677. )
  2678. /*++
  2679. Routine Description:
  2680. An existing file can be deleted using DeleteFile.
  2681. This API provides the same functionality as DOS (int 21h, function 41H)
  2682. and OS/2's DosDelete.
  2683. Arguments:
  2684. lpFileName - Supplies the file name of the file to be deleted.
  2685. Return Value:
  2686. TRUE - The operation was successful.
  2687. FALSE/NULL - The operation failed. Extended error status is available
  2688. using GetLastError.
  2689. --*/
  2690. {
  2691. NTSTATUS Status;
  2692. OBJECT_ATTRIBUTES Obja;
  2693. HANDLE Handle;
  2694. UNICODE_STRING FileName;
  2695. IO_STATUS_BLOCK IoStatusBlock;
  2696. FILE_DISPOSITION_INFORMATION Disposition;
  2697. FILE_ATTRIBUTE_TAG_INFORMATION FileTagInformation;
  2698. BOOLEAN TranslationStatus;
  2699. RTL_RELATIVE_NAME_U RelativeName;
  2700. PVOID FreeBuffer;
  2701. BOOLEAN fIsSymbolicLink = FALSE;
  2702. TranslationStatus = RtlDosPathNameToRelativeNtPathName_U(
  2703. lpFileName,
  2704. &FileName,
  2705. NULL,
  2706. &RelativeName
  2707. );
  2708. if ( !TranslationStatus ) {
  2709. EtwpSetLastError(ERROR_PATH_NOT_FOUND);
  2710. return FALSE;
  2711. }
  2712. FreeBuffer = FileName.Buffer;
  2713. if ( RelativeName.RelativeName.Length ) {
  2714. FileName = RelativeName.RelativeName;
  2715. }
  2716. else {
  2717. RelativeName.ContainingDirectory = NULL;
  2718. }
  2719. InitializeObjectAttributes(
  2720. &Obja,
  2721. &FileName,
  2722. OBJ_CASE_INSENSITIVE,
  2723. RelativeName.ContainingDirectory,
  2724. NULL
  2725. );
  2726. //
  2727. // Open the file for delete access.
  2728. // Inhibit the reparse behavior using FILE_OPEN_REPARSE_POINT.
  2729. //
  2730. Status = NtOpenFile(
  2731. &Handle,
  2732. (ACCESS_MASK)DELETE | FILE_READ_ATTRIBUTES,
  2733. &Obja,
  2734. &IoStatusBlock,
  2735. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  2736. FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT
  2737. );
  2738. if ( !NT_SUCCESS(Status) ) {
  2739. //
  2740. // Back level file systems may not support reparse points and thus not
  2741. // support symbolic links.
  2742. // We infer this is the case when the Status is STATUS_INVALID_PARAMETER.
  2743. //
  2744. if ( Status == STATUS_INVALID_PARAMETER ) {
  2745. //
  2746. // Open without inhibiting the reparse behavior and not needing to
  2747. // read the attributes.
  2748. //
  2749. Status = NtOpenFile(
  2750. &Handle,
  2751. (ACCESS_MASK)DELETE,
  2752. &Obja,
  2753. &IoStatusBlock,
  2754. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  2755. FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT
  2756. );
  2757. if ( !NT_SUCCESS(Status) ) {
  2758. RtlReleaseRelativeName(&RelativeName);
  2759. RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
  2760. EtwpBaseSetLastNTError(Status);
  2761. return FALSE;
  2762. }
  2763. }
  2764. else {
  2765. //
  2766. // A second case of interest is when the caller does not have rights
  2767. // to read attributes yet it does have rights to delete the file.
  2768. // In this case Status is to be STATUS_ACCESS_DENIED.
  2769. //
  2770. if ( Status != STATUS_ACCESS_DENIED ) {
  2771. RtlReleaseRelativeName(&RelativeName);
  2772. RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
  2773. EtwpBaseSetLastNTError(Status);
  2774. return FALSE;
  2775. }
  2776. //
  2777. // Re-open inhibiting reparse point and not requiring read attributes.
  2778. //
  2779. Status = NtOpenFile(
  2780. &Handle,
  2781. (ACCESS_MASK)DELETE,
  2782. &Obja,
  2783. &IoStatusBlock,
  2784. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  2785. FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT
  2786. );
  2787. if ( !NT_SUCCESS(Status) ) {
  2788. RtlReleaseRelativeName(&RelativeName);
  2789. RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
  2790. EtwpBaseSetLastNTError(Status);
  2791. return FALSE;
  2792. }
  2793. //
  2794. // If we are here, Handle is valid.
  2795. //
  2796. // Moreover, Handle is to a file for which the caller has DELETE right yet
  2797. // does not have FILE_READ_ATTRIBUTES rights.
  2798. //
  2799. // The underlying file may or not be a reparse point.
  2800. // As the caller does not have rights to read the attributes this code
  2801. // will delete this file without giving the opportunity to the
  2802. // appropriate manager of these reparse points to clean-up its internal
  2803. // state at this time.
  2804. //
  2805. }
  2806. }
  2807. else {
  2808. //
  2809. // If we found a reparse point that is not a symbolic link, we re-open
  2810. // without inhibiting the reparse behavior.
  2811. //
  2812. Status = NtQueryInformationFile(
  2813. Handle,
  2814. &IoStatusBlock,
  2815. (PVOID) &FileTagInformation,
  2816. sizeof(FileTagInformation),
  2817. FileAttributeTagInformation
  2818. );
  2819. if ( !NT_SUCCESS(Status) ) {
  2820. //
  2821. // Not all File Systems implement all information classes.
  2822. // The value STATUS_INVALID_PARAMETER is returned when a
  2823. // non-supported information class is requested to a back-level
  2824. // File System. As all the parameters to NtQueryInformationFile
  2825. // are correct, we can infer that we found a back-level system.
  2826. //
  2827. // If FileAttributeTagInformation is not implemented, we assume that
  2828. // the file at hand is not a reparse point.
  2829. //
  2830. if ( (Status != STATUS_NOT_IMPLEMENTED) &&
  2831. (Status != STATUS_INVALID_PARAMETER) ) {
  2832. RtlReleaseRelativeName(&RelativeName);
  2833. RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
  2834. NtClose(Handle);
  2835. EtwpBaseSetLastNTError(Status);
  2836. return FALSE;
  2837. }
  2838. }
  2839. if ( NT_SUCCESS(Status) &&
  2840. (FileTagInformation.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ) {
  2841. if ( FileTagInformation.ReparseTag == IO_REPARSE_TAG_MOUNT_POINT ) {
  2842. fIsSymbolicLink = TRUE;
  2843. }
  2844. }
  2845. if ( NT_SUCCESS(Status) &&
  2846. (FileTagInformation.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
  2847. !fIsSymbolicLink) {
  2848. //
  2849. // Re-open without inhibiting the reparse behavior and not needing to
  2850. // read the attributes.
  2851. //
  2852. NtClose(Handle);
  2853. Status = NtOpenFile(
  2854. &Handle,
  2855. (ACCESS_MASK)DELETE,
  2856. &Obja,
  2857. &IoStatusBlock,
  2858. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  2859. FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT
  2860. );
  2861. if ( !NT_SUCCESS(Status) ) {
  2862. //
  2863. // When the FS Filter is absent, delete it any way.
  2864. //
  2865. if ( Status == STATUS_IO_REPARSE_TAG_NOT_HANDLED ) {
  2866. //
  2867. // We re-open (possible 3rd open) for delete access
  2868. // inhibiting the reparse behavior.
  2869. //
  2870. Status = NtOpenFile(
  2871. &Handle,
  2872. (ACCESS_MASK)DELETE,
  2873. &Obja,
  2874. &IoStatusBlock,
  2875. FILE_SHARE_READ | FILE_SHARE_WRITE |
  2876. FILE_SHARE_DELETE,
  2877. FILE_NON_DIRECTORY_FILE |
  2878. FILE_OPEN_FOR_BACKUP_INTENT |
  2879. FILE_OPEN_REPARSE_POINT
  2880. );
  2881. }
  2882. if ( !NT_SUCCESS(Status) ) {
  2883. RtlReleaseRelativeName(&RelativeName);
  2884. RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
  2885. EtwpBaseSetLastNTError(Status);
  2886. return FALSE;
  2887. }
  2888. }
  2889. }
  2890. }
  2891. RtlReleaseRelativeName(&RelativeName);
  2892. RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
  2893. //
  2894. // Delete the file
  2895. //
  2896. #undef DeleteFile
  2897. Disposition.DeleteFile = TRUE;
  2898. Status = NtSetInformationFile(
  2899. Handle,
  2900. &IoStatusBlock,
  2901. &Disposition,
  2902. sizeof(Disposition),
  2903. FileDispositionInformation
  2904. );
  2905. NtClose(Handle);
  2906. if ( NT_SUCCESS(Status) ) {
  2907. return TRUE;
  2908. }
  2909. else {
  2910. EtwpBaseSetLastNTError(Status);
  2911. return FALSE;
  2912. }
  2913. }
  2914. UINT
  2915. APIENTRY
  2916. EtwpGetSystemDirectoryW(
  2917. LPWSTR lpBuffer,
  2918. UINT uSize
  2919. )
  2920. /*++
  2921. Routine Description:
  2922. This function obtains the pathname of the Windows system
  2923. subdirectory. The system subdirectory contains such files as
  2924. Windows libraries, drivers, and font files.
  2925. The pathname retrieved by this function does not end with a
  2926. backslash unless the system directory is the root directory. For
  2927. example, if the system directory is named WINDOWS\SYSTEM on drive
  2928. C:, the pathname of the system subdirectory retrieved by this
  2929. function is C:\WINDOWS\SYSTEM.
  2930. Arguments:
  2931. lpBuffer - Points to the buffer that is to receive the
  2932. null-terminated character string containing the pathname.
  2933. uSize - Specifies the maximum size (in bytes) of the buffer. This
  2934. value should be set to at least MAX_PATH to allow sufficient room in
  2935. the buffer for the pathname.
  2936. Return Value:
  2937. The return value is the length of the string copied to lpBuffer, not
  2938. including the terminating null character. If the return value is
  2939. greater than uSize, the return value is the size of the buffer
  2940. required to hold the pathname. The return value is zero if the
  2941. function failed.
  2942. --*/
  2943. {
  2944. UNICODE_STRING WindowsSystemDirectory;
  2945. PBASE_STATIC_SERVER_DATA tmpBaseStaticServerData = BASE_SHARED_SERVER_DATA;
  2946. #ifdef WX86
  2947. if (NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll) {
  2948. NtCurrentTeb()->Wx86Thread.UseKnownWx86Dll = FALSE;
  2949. BASE_SERVER_STR_TO_LOCAL_STR(&WindowsSystemDirectory, &tmpBaseStaticServerData->WindowsSys32x86Directory);
  2950. }
  2951. #else
  2952. BASE_SERVER_STR_TO_LOCAL_STR(&WindowsSystemDirectory, &tmpBaseStaticServerData->WindowsDirectory);
  2953. #endif
  2954. if ( uSize*2 < WindowsSystemDirectory.MaximumLength ) {
  2955. return WindowsSystemDirectory.MaximumLength/2;
  2956. }
  2957. RtlMoveMemory(
  2958. lpBuffer,
  2959. WindowsSystemDirectory.Buffer,
  2960. WindowsSystemDirectory.Length
  2961. );
  2962. lpBuffer[(WindowsSystemDirectory.Length>>1)] = UNICODE_NULL;
  2963. return WindowsSystemDirectory.Length/2;
  2964. }
  2965. ///
  2966. /// Duplicated code form intlrndp.c
  2967. ///
  2968. #define DEFAULT_GUID_COUNT 100
  2969. ULONG
  2970. EtwpEnumRegGuids(
  2971. PWMIGUIDLISTINFO *pGuidInfo
  2972. )
  2973. {
  2974. ULONG Status = ERROR_SUCCESS;
  2975. ULONG MaxGuidCount = 0;
  2976. PWMIGUIDLISTINFO GuidInfo;
  2977. ULONG RetSize=0;
  2978. ULONG GuidInfoSize;
  2979. MaxGuidCount = DEFAULT_GUID_COUNT;
  2980. retry:
  2981. GuidInfoSize = FIELD_OFFSET(WMIGUIDLISTINFO, GuidList) +
  2982. MaxGuidCount * sizeof(WMIGUIDPROPERTIES);
  2983. GuidInfo = (PWMIGUIDLISTINFO)EtwpAlloc(GuidInfoSize);
  2984. if (GuidInfo == NULL)
  2985. {
  2986. return (ERROR_NOT_ENOUGH_MEMORY);
  2987. }
  2988. RtlZeroMemory(GuidInfo, GuidInfoSize);
  2989. Status = EtwpSendWmiKMRequest(NULL,
  2990. IOCTL_WMI_ENUMERATE_GUIDS_AND_PROPERTIES,
  2991. GuidInfo,
  2992. GuidInfoSize,
  2993. GuidInfo,
  2994. GuidInfoSize,
  2995. &RetSize,
  2996. NULL);
  2997. if (Status == ERROR_SUCCESS)
  2998. {
  2999. if ((RetSize < FIELD_OFFSET(WMIGUIDLISTINFO, GuidList)) ||
  3000. (RetSize < (FIELD_OFFSET(WMIGUIDLISTINFO, GuidList) +
  3001. GuidInfo->ReturnedGuidCount * sizeof(WMIGUIDPROPERTIES))))
  3002. {
  3003. //
  3004. // WMI KM returned to us a bad size which should not happen
  3005. //
  3006. Status = ERROR_WMI_DP_FAILED;
  3007. EtwpAssert(FALSE);
  3008. EtwpFree(GuidInfo);
  3009. } else {
  3010. //
  3011. // If RPC was successful, then build a WMI DataBlock with the data
  3012. //
  3013. if (GuidInfo->TotalGuidCount > GuidInfo->ReturnedGuidCount) {
  3014. MaxGuidCount = GuidInfo->TotalGuidCount;
  3015. EtwpFree(GuidInfo);
  3016. goto retry;
  3017. }
  3018. }
  3019. //
  3020. // If the call was successful, return the pointers and the caller
  3021. // must free the storage.
  3022. //
  3023. *pGuidInfo = GuidInfo;
  3024. }
  3025. return Status;
  3026. }
  3027. ///////
  3028. ////// Duplicated from chunkimp.h
  3029. //////
  3030. ULONG EtwpBuildGuidObjectAttributes(
  3031. IN LPGUID Guid,
  3032. OUT POBJECT_ATTRIBUTES ObjectAttributes,
  3033. OUT PUNICODE_STRING GuidString,
  3034. OUT PWCHAR GuidObjectName
  3035. )
  3036. {
  3037. WCHAR GuidChar[37];
  3038. HRESULT hr;
  3039. EtwpAssert(Guid != NULL);
  3040. EtwpAssert(GuidString != NULL);
  3041. EtwpAssert(GuidObjectName != NULL);
  3042. //
  3043. // Build up guid name into the ObjectAttributes
  3044. //
  3045. hr = StringCbPrintfW(GuidChar, sizeof(GuidChar),L"%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
  3046. Guid->Data1, Guid->Data2,
  3047. Guid->Data3,
  3048. Guid->Data4[0], Guid->Data4[1],
  3049. Guid->Data4[2], Guid->Data4[3],
  3050. Guid->Data4[4], Guid->Data4[5],
  3051. Guid->Data4[6], Guid->Data4[7]);
  3052. WmipAssert(hr == S_OK);
  3053. hr = StringCchCopyW(GuidObjectName,
  3054. WmiGuidObjectNameLength+1,
  3055. WmiGuidObjectDirectory);
  3056. WmipAssert(hr == S_OK);
  3057. hr = StringCchCatW(GuidObjectName,
  3058. WmiGuidObjectNameLength+1,
  3059. GuidChar);
  3060. WmipAssert(hr == S_OK);
  3061. RtlInitUnicodeString(GuidString, GuidObjectName);
  3062. memset(ObjectAttributes, 0, sizeof(OBJECT_ATTRIBUTES));
  3063. ObjectAttributes->Length = sizeof(OBJECT_ATTRIBUTES);
  3064. ObjectAttributes->ObjectName = GuidString;
  3065. return(ERROR_SUCCESS);
  3066. }
  3067. ///////
  3068. ////// Duplicated from chunkimp.h
  3069. //////
  3070. ULONG EtwpCheckGuidAccess(
  3071. LPGUID Guid,
  3072. ACCESS_MASK DesiredAccess
  3073. )
  3074. {
  3075. HANDLE Handle;
  3076. ULONG Status;
  3077. Status = EtwpOpenKernelGuid(Guid,
  3078. DesiredAccess,
  3079. &Handle,
  3080. IOCTL_WMI_OPEN_GUID
  3081. );
  3082. if (Status == ERROR_SUCCESS)
  3083. {
  3084. EtwpCloseHandle(Handle);
  3085. }
  3086. return(Status);
  3087. }
  3088. ///////
  3089. ////// Duplicated from chunkimp.h
  3090. //////
  3091. ULONG EtwpOpenKernelGuid(
  3092. LPGUID Guid,
  3093. ACCESS_MASK DesiredAccess,
  3094. PHANDLE Handle,
  3095. ULONG Ioctl
  3096. )
  3097. {
  3098. WMIOPENGUIDBLOCK WmiOpenGuidBlock;
  3099. UNICODE_STRING GuidString;
  3100. ULONG ReturnSize;
  3101. ULONG Status;
  3102. WCHAR GuidObjectName[WmiGuidObjectNameLength+1];
  3103. OBJECT_ATTRIBUTES ObjectAttributes;
  3104. Status = EtwpBuildGuidObjectAttributes(Guid,
  3105. &ObjectAttributes,
  3106. &GuidString,
  3107. GuidObjectName);
  3108. if (Status == ERROR_SUCCESS)
  3109. {
  3110. WmiOpenGuidBlock.ObjectAttributes = &ObjectAttributes;
  3111. WmiOpenGuidBlock.DesiredAccess = DesiredAccess;
  3112. Status = EtwpSendWmiKMRequest(NULL,
  3113. Ioctl,
  3114. (PVOID)&WmiOpenGuidBlock,
  3115. sizeof(WMIOPENGUIDBLOCK),
  3116. (PVOID)&WmiOpenGuidBlock,
  3117. sizeof(WMIOPENGUIDBLOCK),
  3118. &ReturnSize,
  3119. NULL);
  3120. if (Status == ERROR_SUCCESS)
  3121. {
  3122. *Handle = WmiOpenGuidBlock.Handle.Handle;
  3123. } else {
  3124. *Handle = NULL;
  3125. }
  3126. }
  3127. return(Status);
  3128. }
  3129. DWORD
  3130. EtwpExpandEnvironmentStringsW(
  3131. LPCWSTR lpSrc,
  3132. LPWSTR lpDst,
  3133. DWORD nSize
  3134. )
  3135. {
  3136. NTSTATUS Status;
  3137. UNICODE_STRING Source, Destination;
  3138. ULONG Length;
  3139. DWORD iSize;
  3140. if ( nSize > (MAXUSHORT >> 1)-2 ) {
  3141. iSize = (MAXUSHORT >> 1)-2;
  3142. }
  3143. else {
  3144. iSize = nSize;
  3145. }
  3146. RtlInitUnicodeString( &Source, lpSrc );
  3147. Destination.Buffer = lpDst;
  3148. Destination.Length = 0;
  3149. Destination.MaximumLength = (USHORT)(iSize * sizeof( WCHAR ));
  3150. Length = 0;
  3151. Status = RtlExpandEnvironmentStrings_U( NULL,
  3152. &Source,
  3153. &Destination,
  3154. &Length
  3155. );
  3156. if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_TOO_SMALL) {
  3157. return( Length / sizeof( WCHAR ) );
  3158. }
  3159. else {
  3160. EtwpBaseSetLastNTError( Status );
  3161. return( 0 );
  3162. }
  3163. }
  3164. HANDLE
  3165. EtwpBaseFindFirstDevice(
  3166. PCUNICODE_STRING FileName,
  3167. LPWIN32_FIND_DATAW lpFindFileData
  3168. )
  3169. /*++
  3170. Routine Description:
  3171. This function is called when find first file encounters a device
  3172. name. This function returns a successful psuedo file handle and
  3173. fills in the find file data with all zeros and the devic name.
  3174. Arguments:
  3175. FileName - Supplies the device name of the file to find.
  3176. lpFindFileData - On a successful find, this parameter returns information
  3177. about the located file.
  3178. Return Value:
  3179. Always returns a static find file handle value of
  3180. BASE_FIND_FIRST_DEVICE_HANDLE
  3181. --*/
  3182. {
  3183. RtlZeroMemory(lpFindFileData,sizeof(*lpFindFileData));
  3184. lpFindFileData->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
  3185. //
  3186. // Check for size just to be safe
  3187. //
  3188. if (FileName->MaximumLength <= MAX_PATH * sizeof(WCHAR)) {
  3189. RtlMoveMemory(
  3190. &lpFindFileData->cFileName[0],
  3191. FileName->Buffer,
  3192. FileName->MaximumLength
  3193. );
  3194. }
  3195. else {
  3196. #if DBG
  3197. EtwpAssert(FALSE);
  3198. #endif
  3199. EtwpSetLastError(ERROR_BUFFER_OVERFLOW);
  3200. return INVALID_HANDLE_VALUE;
  3201. }
  3202. return BASE_FIND_FIRST_DEVICE_HANDLE;
  3203. }
  3204. PFINDFILE_HANDLE
  3205. EtwpBasepInitializeFindFileHandle(
  3206. IN HANDLE DirectoryHandle
  3207. )
  3208. {
  3209. PFINDFILE_HANDLE FindFileHandle;
  3210. FindFileHandle = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( FIND_TAG ), sizeof(*FindFileHandle));
  3211. if ( FindFileHandle ) {
  3212. FindFileHandle->DirectoryHandle = DirectoryHandle;
  3213. FindFileHandle->FindBufferBase = NULL;
  3214. FindFileHandle->FindBufferNext = NULL;
  3215. FindFileHandle->FindBufferLength = 0;
  3216. FindFileHandle->FindBufferValidLength = 0;
  3217. if ( !NT_SUCCESS(RtlInitializeCriticalSection(&FindFileHandle->FindBufferLock)) ){
  3218. RtlFreeHeap(RtlProcessHeap(), 0,FindFileHandle);
  3219. FindFileHandle = NULL;
  3220. }
  3221. }
  3222. return FindFileHandle;
  3223. }
  3224. HANDLE
  3225. EtwpFindFirstFileExW(
  3226. LPCWSTR lpFileName,
  3227. FINDEX_INFO_LEVELS fInfoLevelId,
  3228. LPVOID lpFindFileData,
  3229. FINDEX_SEARCH_OPS fSearchOp,
  3230. LPVOID lpSearchFilter,
  3231. DWORD dwAdditionalFlags
  3232. )
  3233. /*++
  3234. Routine Description:
  3235. A directory can be searched for the first entry whose name and
  3236. attributes match the specified name using FindFirstFileEx.
  3237. This API is provided to open a find file handle and return
  3238. information about the first file whose name matchs the specified
  3239. pattern. If the fSearchOp is FindExSearchNameMatch, then that is
  3240. the extent of the filtering, and lpSearchFilter MUST be NULL.
  3241. Otherwise, additional subfiltering is done depending on this value.
  3242. FindExSearchLimitToDirectories - If this search op is specified,
  3243. then lpSearchFilter MUST be NULL. For each file that
  3244. matches the specified filename, and that is a directory, and
  3245. entry for that file is returned.
  3246. If the underlying file/io system does not support this type
  3247. of filtering, the API will fail with ERROR_NOT_SUPPORTED,
  3248. and the application will have to perform its own filtering
  3249. by calling this API with FindExSearchNameMatch.
  3250. FindExSearchLimitToDevices - If this search op is specified, the
  3251. lpFileName MUST be *, and FIND_FIRST_EX_CASE_SENSITIVE
  3252. must NOT be specified. Only device names are returned.
  3253. Device names are generally accessible through
  3254. \\.\name-of-device naming.
  3255. The data returned by this API is dependent on the fInfoLevelId.
  3256. FindExInfoStandard - The lpFindFileData pointer is the standard
  3257. LPWIN32_FIND_DATA structure.
  3258. At this time, no other information levels are supported
  3259. Once established, the find file handle can be used to search for
  3260. other files that match the same pattern with the same filtering
  3261. being performed. When the find file handle is no longer needed, it
  3262. should be closed.
  3263. Note that while this interface only returns information for a single
  3264. file, an implementation is free to buffer several matching files
  3265. that can be used to satisfy subsequent calls to FindNextFileEx.
  3266. This API is a complete superset of existing FindFirstFile. FindFirstFile
  3267. could be coded as the following macro:
  3268. #define FindFirstFile(a,b)
  3269. FindFirstFileEx((a),FindExInfoStandard,(b),FindExSearchNameMatch,NULL,0);
  3270. Arguments:
  3271. lpFileName - Supplies the file name of the file to find. The file name
  3272. may contain the DOS wild card characters '*' and '?'.
  3273. fInfoLevelId - Supplies the info level of the returned data.
  3274. lpFindFileData - Supplies a pointer whose type is dependent on the value
  3275. of fInfoLevelId. This buffer returns the appropriate file data.
  3276. fSearchOp - Specified the type of filtering to perform above and
  3277. beyond simple wildcard matching.
  3278. lpSearchFilter - If the specified fSearchOp needs structured search
  3279. information, this pointer points to the search criteria. At
  3280. this point in time, both search ops do not require extended
  3281. search information, so this pointer is NULL.
  3282. dwAdditionalFlags - Supplies additional flag values that control the
  3283. search. A flag value of FIND_FIRST_EX_CASE_SENSITIVE can be
  3284. used to cause case sensitive searches to occur. The default is
  3285. case insensitive.
  3286. Return Value:
  3287. Not -1 - Returns a find first handle that can be used in a
  3288. subsequent call to FindNextFileEx or FindClose.
  3289. 0xffffffff - The operation failed. Extended error status is available
  3290. using GetLastError.
  3291. --*/
  3292. {
  3293. #define FIND_FIRST_EX_INVALID_FLAGS (~FIND_FIRST_EX_CASE_SENSITIVE)
  3294. HANDLE hFindFile;
  3295. NTSTATUS Status;
  3296. OBJECT_ATTRIBUTES Obja;
  3297. UNICODE_STRING FileName;
  3298. UNICODE_STRING PathName;
  3299. IO_STATUS_BLOCK IoStatusBlock;
  3300. PFILE_BOTH_DIR_INFORMATION DirectoryInfo;
  3301. struct SEARCH_BUFFER {
  3302. FILE_BOTH_DIR_INFORMATION DirInfo;
  3303. WCHAR Names[MAX_PATH];
  3304. } Buffer;
  3305. BOOLEAN TranslationStatus;
  3306. RTL_RELATIVE_NAME_U RelativeName;
  3307. PVOID FreeBuffer;
  3308. UNICODE_STRING UnicodeInput;
  3309. PFINDFILE_HANDLE FindFileHandle;
  3310. BOOLEAN EndsInDot;
  3311. LPWIN32_FIND_DATAW FindFileData;
  3312. BOOLEAN StrippedTrailingSlash;
  3313. //
  3314. // check parameters
  3315. //
  3316. if ( fInfoLevelId >= FindExInfoMaxInfoLevel ||
  3317. fSearchOp >= FindExSearchLimitToDevices ||
  3318. dwAdditionalFlags & FIND_FIRST_EX_INVALID_FLAGS ) {
  3319. EtwpSetLastError(fSearchOp == FindExSearchLimitToDevices ? ERROR_NOT_SUPPORTED : ERROR_INVALID_PARAMETER);
  3320. return INVALID_HANDLE_VALUE;
  3321. }
  3322. FindFileData = (LPWIN32_FIND_DATAW)lpFindFileData;
  3323. RtlInitUnicodeString(&UnicodeInput,lpFileName);
  3324. //
  3325. // Bogus code to workaround ~* problem
  3326. //
  3327. if ( UnicodeInput.Buffer[(UnicodeInput.Length>>1)-1] == (WCHAR)'.' ) {
  3328. EndsInDot = TRUE;
  3329. }
  3330. else {
  3331. EndsInDot = FALSE;
  3332. }
  3333. TranslationStatus = RtlDosPathNameToRelativeNtPathName_U(
  3334. lpFileName,
  3335. &PathName,
  3336. &FileName.Buffer,
  3337. &RelativeName
  3338. );
  3339. if ( !TranslationStatus ) {
  3340. EtwpSetLastError(ERROR_PATH_NOT_FOUND);
  3341. return INVALID_HANDLE_VALUE;
  3342. }
  3343. FreeBuffer = PathName.Buffer;
  3344. //
  3345. // If there is a a file portion of this name, determine the length
  3346. // of the name for a subsequent call to NtQueryDirectoryFile.
  3347. //
  3348. if (FileName.Buffer) {
  3349. FileName.Length =
  3350. PathName.Length - (USHORT)((ULONG_PTR)FileName.Buffer - (ULONG_PTR)PathName.Buffer);
  3351. } else {
  3352. FileName.Length = 0;
  3353. }
  3354. FileName.MaximumLength = FileName.Length;
  3355. if ( RelativeName.RelativeName.Length &&
  3356. RelativeName.RelativeName.Buffer != FileName.Buffer ) {
  3357. if (FileName.Buffer) {
  3358. PathName.Length = (USHORT)((ULONG_PTR)FileName.Buffer - (ULONG_PTR)RelativeName.RelativeName.Buffer);
  3359. PathName.MaximumLength = PathName.Length;
  3360. PathName.Buffer = RelativeName.RelativeName.Buffer;
  3361. }
  3362. }
  3363. else {
  3364. RelativeName.ContainingDirectory = NULL;
  3365. if (FileName.Buffer) {
  3366. PathName.Length = (USHORT)((ULONG_PTR)FileName.Buffer - (ULONG_PTR)PathName.Buffer);
  3367. PathName.MaximumLength = PathName.Length;
  3368. }
  3369. }
  3370. if ( PathName.Buffer[(PathName.Length>>1)-2] != (WCHAR)':' &&
  3371. PathName.Buffer[(PathName.Length>>1)-1] != (WCHAR)'\\' ) {
  3372. PathName.Length -= sizeof(UNICODE_NULL);
  3373. StrippedTrailingSlash = TRUE;
  3374. }
  3375. else {
  3376. StrippedTrailingSlash = FALSE;
  3377. }
  3378. InitializeObjectAttributes(
  3379. &Obja,
  3380. &PathName,
  3381. (dwAdditionalFlags & FIND_FIRST_EX_CASE_SENSITIVE) ? 0 : OBJ_CASE_INSENSITIVE,
  3382. RelativeName.ContainingDirectory,
  3383. NULL
  3384. );
  3385. //
  3386. // Open the directory for list access
  3387. //
  3388. Status = NtOpenFile(
  3389. &hFindFile,
  3390. FILE_LIST_DIRECTORY | SYNCHRONIZE,
  3391. &Obja,
  3392. &IoStatusBlock,
  3393. FILE_SHARE_READ | FILE_SHARE_WRITE,
  3394. FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT
  3395. );
  3396. if ( (Status == STATUS_INVALID_PARAMETER ||
  3397. Status == STATUS_NOT_A_DIRECTORY) && StrippedTrailingSlash ) {
  3398. //
  3399. // open of a pnp style path failed, so try putting back the trailing slash
  3400. //
  3401. PathName.Length += sizeof(UNICODE_NULL);
  3402. Status = NtOpenFile(
  3403. &hFindFile,
  3404. FILE_LIST_DIRECTORY | SYNCHRONIZE,
  3405. &Obja,
  3406. &IoStatusBlock,
  3407. FILE_SHARE_READ | FILE_SHARE_WRITE,
  3408. FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT
  3409. );
  3410. PathName.Length -= sizeof(UNICODE_NULL);
  3411. }
  3412. if ( !NT_SUCCESS(Status) ) {
  3413. ULONG DeviceNameData;
  3414. UNICODE_STRING DeviceName;
  3415. RtlReleaseRelativeName(&RelativeName);
  3416. RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
  3417. //
  3418. // The full path does not refer to a directory. This could
  3419. // be a device. Check for a device name.
  3420. //
  3421. if ( DeviceNameData = RtlIsDosDeviceName_U(UnicodeInput.Buffer) ) {
  3422. DeviceName.Length = (USHORT)(DeviceNameData & 0xffff);
  3423. DeviceName.MaximumLength = (USHORT)(DeviceNameData & 0xffff);
  3424. DeviceName.Buffer = (PWSTR)
  3425. ((PUCHAR)UnicodeInput.Buffer + (DeviceNameData >> 16));
  3426. return EtwpBaseFindFirstDevice(&DeviceName,FindFileData);
  3427. }
  3428. if ( Status == STATUS_OBJECT_NAME_NOT_FOUND ) {
  3429. Status = STATUS_OBJECT_PATH_NOT_FOUND;
  3430. }
  3431. if ( Status == STATUS_OBJECT_TYPE_MISMATCH ) {
  3432. Status = STATUS_OBJECT_PATH_NOT_FOUND;
  3433. }
  3434. EtwpBaseSetLastNTError(Status);
  3435. return INVALID_HANDLE_VALUE;
  3436. }
  3437. //
  3438. // Get an entry
  3439. //
  3440. //
  3441. // If there is no file part, but we are not looking at a device,
  3442. // then bail.
  3443. //
  3444. if ( !FileName.Length ) {
  3445. RtlReleaseRelativeName(&RelativeName);
  3446. RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
  3447. NtClose(hFindFile);
  3448. EtwpSetLastError(ERROR_FILE_NOT_FOUND);
  3449. return INVALID_HANDLE_VALUE;
  3450. }
  3451. DirectoryInfo = &Buffer.DirInfo;
  3452. //
  3453. // Special case *.* to * since it is so common. Otherwise transmogrify
  3454. // the input name according to the following rules:
  3455. //
  3456. // - Change all ? to DOS_QM
  3457. // - Change all . followed by ? or * to DOS_DOT
  3458. // - Change all * followed by a . into DOS_STAR
  3459. //
  3460. // These transmogrifications are all done in place.
  3461. //
  3462. if ( (FileName.Length == 6) &&
  3463. (RtlCompareMemory(FileName.Buffer, L"*.*", 6) == 6) ) {
  3464. FileName.Length = 2;
  3465. } else {
  3466. ULONG Index;
  3467. WCHAR *NameChar;
  3468. for ( Index = 0, NameChar = FileName.Buffer;
  3469. Index < FileName.Length/sizeof(WCHAR);
  3470. Index += 1, NameChar += 1) {
  3471. if (Index && (*NameChar == L'.') && (*(NameChar - 1) == L'*')) {
  3472. *(NameChar - 1) = DOS_STAR;
  3473. }
  3474. if ((*NameChar == L'?') || (*NameChar == L'*')) {
  3475. if (*NameChar == L'?') { *NameChar = DOS_QM; }
  3476. if (Index && *(NameChar-1) == L'.') { *(NameChar-1) = DOS_DOT; }
  3477. }
  3478. }
  3479. if (EndsInDot && *(NameChar - 1) == L'*') { *(NameChar-1) = DOS_STAR; }
  3480. }
  3481. Status = NtQueryDirectoryFile(
  3482. hFindFile,
  3483. NULL,
  3484. NULL,
  3485. NULL,
  3486. &IoStatusBlock,
  3487. DirectoryInfo,
  3488. sizeof(Buffer),
  3489. FileBothDirectoryInformation,
  3490. TRUE,
  3491. &FileName,
  3492. FALSE
  3493. );
  3494. RtlReleaseRelativeName(&RelativeName);
  3495. RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
  3496. if ( !NT_SUCCESS(Status) ) {
  3497. NtClose(hFindFile);
  3498. EtwpBaseSetLastNTError(Status);
  3499. return INVALID_HANDLE_VALUE;
  3500. }
  3501. //
  3502. // Attributes are composed of the attributes returned by NT.
  3503. //
  3504. FindFileData->dwFileAttributes = DirectoryInfo->FileAttributes;
  3505. FindFileData->ftCreationTime = *(LPFILETIME)&DirectoryInfo->CreationTime;
  3506. FindFileData->ftLastAccessTime = *(LPFILETIME)&DirectoryInfo->LastAccessTime;
  3507. FindFileData->ftLastWriteTime = *(LPFILETIME)&DirectoryInfo->LastWriteTime;
  3508. FindFileData->nFileSizeHigh = DirectoryInfo->EndOfFile.HighPart;
  3509. FindFileData->nFileSizeLow = DirectoryInfo->EndOfFile.LowPart;
  3510. RtlMoveMemory( FindFileData->cFileName,
  3511. DirectoryInfo->FileName,
  3512. DirectoryInfo->FileNameLength );
  3513. FindFileData->cFileName[DirectoryInfo->FileNameLength >> 1] = UNICODE_NULL;
  3514. RtlMoveMemory( FindFileData->cAlternateFileName,
  3515. DirectoryInfo->ShortName,
  3516. DirectoryInfo->ShortNameLength );
  3517. FindFileData->cAlternateFileName[DirectoryInfo->ShortNameLength >> 1] = UNICODE_NULL;
  3518. //
  3519. // For NTFS reparse points we return the reparse point data tag in dwReserved0.
  3520. //
  3521. if ( DirectoryInfo->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ) {
  3522. FindFileData->dwReserved0 = DirectoryInfo->EaSize;
  3523. }
  3524. FindFileHandle = EtwpBasepInitializeFindFileHandle(hFindFile);
  3525. if ( !FindFileHandle ) {
  3526. NtClose(hFindFile);
  3527. EtwpSetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3528. return INVALID_HANDLE_VALUE;
  3529. }
  3530. return (HANDLE)FindFileHandle;
  3531. }
  3532. HANDLE
  3533. EtwpFindFirstFileW(
  3534. LPCWSTR lpFileName,
  3535. LPWIN32_FIND_DATAW lpFindFileData
  3536. )
  3537. /*++
  3538. Routine Description:
  3539. A directory can be searched for the first entry whose name and
  3540. attributes match the specified name using FindFirstFile.
  3541. This API is provided to open a find file handle and return
  3542. information about the first file whose name match the specified
  3543. pattern. Once established, the find file handle can be used to
  3544. search for other files that match the same pattern. When the find
  3545. file handle is no longer needed, it should be closed.
  3546. Note that while this interface only returns information for a single
  3547. file, an implementation is free to buffer several matching files
  3548. that can be used to satisfy subsequent calls to FindNextFile. Also
  3549. not that matches are done by name only. This API does not do
  3550. attribute based matching.
  3551. This API is similar to DOS (int 21h, function 4Eh), and OS/2's
  3552. DosFindFirst. For portability reasons, its data structures and
  3553. parameter passing is somewhat different.
  3554. Arguments:
  3555. lpFileName - Supplies the file name of the file to find. The file name
  3556. may contain the DOS wild card characters '*' and '?'.
  3557. lpFindFileData - On a successful find, this parameter returns information
  3558. about the located file:
  3559. WIN32_FIND_DATA Structure:
  3560. DWORD dwFileAttributes - Returns the file attributes of the found
  3561. file.
  3562. FILETIME ftCreationTime - Returns the time that the file was created.
  3563. A value of 0,0 specifies that the file system containing the
  3564. file does not support this time field.
  3565. FILETIME ftLastAccessTime - Returns the time that the file was last
  3566. accessed. A value of 0,0 specifies that the file system
  3567. containing the file does not support this time field.
  3568. FILETIME ftLastWriteTime - Returns the time that the file was last
  3569. written. A file systems support this time field.
  3570. DWORD nFileSizeHigh - Returns the high order 32 bits of the
  3571. file's size.
  3572. DWORD nFileSizeLow - Returns the low order 32-bits of the file's
  3573. size in bytes.
  3574. UCHAR cFileName[MAX_PATH] - Returns the null terminated name of
  3575. the file.
  3576. Return Value:
  3577. Not -1 - Returns a find first handle
  3578. that can be used in a subsequent call to FindNextFile or FindClose.
  3579. 0xffffffff - The operation failed. Extended error status is available
  3580. using GetLastError.
  3581. --*/
  3582. {
  3583. return EtwpFindFirstFileExW(
  3584. lpFileName,
  3585. FindExInfoStandard,
  3586. lpFindFileData,
  3587. FindExSearchNameMatch,
  3588. NULL,
  3589. 0
  3590. );
  3591. }
  3592. BOOL
  3593. EtwpFindClose(
  3594. HANDLE hFindFile
  3595. )
  3596. /*++
  3597. Routine Description:
  3598. A find file context created by FindFirstFile can be closed using
  3599. FindClose.
  3600. This API is used to inform the system that a find file handle
  3601. created by FindFirstFile is no longer needed. On systems that
  3602. maintain internal state for each find file context, this API informs
  3603. the system that this state no longer needs to be maintained.
  3604. Once this call has been made, the hFindFile may not be used in a
  3605. subsequent call to either FindNextFile or FindClose.
  3606. This API has no DOS counterpart, but is similar to OS/2's
  3607. DosFindClose.
  3608. Arguments:
  3609. hFindFile - Supplies a find file handle returned in a previous call
  3610. to FindFirstFile that is no longer needed.
  3611. Return Value:
  3612. TRUE - The operation was successful.
  3613. FALSE/NULL - The operation failed. Extended error status is available
  3614. using GetLastError.
  3615. --*/
  3616. {
  3617. NTSTATUS Status;
  3618. PFINDFILE_HANDLE FindFileHandle;
  3619. HANDLE DirectoryHandle;
  3620. PVOID FindBufferBase;
  3621. if ( hFindFile == BASE_FIND_FIRST_DEVICE_HANDLE ) {
  3622. return TRUE;
  3623. }
  3624. if ( hFindFile == INVALID_HANDLE_VALUE ) {
  3625. EtwpSetLastError(ERROR_INVALID_HANDLE);
  3626. return FALSE;
  3627. }
  3628. try {
  3629. FindFileHandle = (PFINDFILE_HANDLE)hFindFile;
  3630. RtlEnterCriticalSection(&FindFileHandle->FindBufferLock);
  3631. DirectoryHandle = FindFileHandle->DirectoryHandle;
  3632. FindBufferBase = FindFileHandle->FindBufferBase;
  3633. FindFileHandle->DirectoryHandle = INVALID_HANDLE_VALUE;
  3634. FindFileHandle->FindBufferBase = NULL;
  3635. RtlLeaveCriticalSection(&FindFileHandle->FindBufferLock);
  3636. Status = NtClose(DirectoryHandle);
  3637. if ( NT_SUCCESS(Status) ) {
  3638. if (FindBufferBase) {
  3639. RtlFreeHeap(RtlProcessHeap(), 0,FindBufferBase);
  3640. }
  3641. RtlDeleteCriticalSection(&FindFileHandle->FindBufferLock);
  3642. RtlFreeHeap(RtlProcessHeap(), 0,FindFileHandle);
  3643. return TRUE;
  3644. }
  3645. else {
  3646. EtwpBaseSetLastNTError(Status);
  3647. return FALSE;
  3648. }
  3649. }
  3650. except ( EXCEPTION_EXECUTE_HANDLER ) {
  3651. EtwpBaseSetLastNTError(GetExceptionCode());
  3652. return FALSE;
  3653. }
  3654. return FALSE;
  3655. }
  3656. UINT
  3657. APIENTRY
  3658. EtwpGetSystemWindowsDirectoryW(
  3659. LPWSTR lpBuffer,
  3660. UINT uSize
  3661. )
  3662. /*++
  3663. Routine Description:
  3664. This function obtains the pathname of the system Windows directory.
  3665. Arguments:
  3666. lpBuffer - Points to the buffer that is to receive the
  3667. null-terminated character string containing the pathname.
  3668. uSize - Specifies the maximum size (in wchars) of the buffer. This
  3669. value should be set to at least MAX_PATH to allow sufficient room in
  3670. the buffer for the pathname.
  3671. Return Value:
  3672. The return value is the length of the string copied to lpBuffer, not
  3673. including the terminating null character. If the return value is
  3674. greater than uSize, the return value is the size of the buffer
  3675. required to hold the pathname. The return value is zero if the
  3676. function failed.
  3677. --*/
  3678. {
  3679. UNICODE_STRING tmpBaseWindowsDirectory;
  3680. PBASE_STATIC_SERVER_DATA tmpBaseStaticServerData = BASE_SHARED_SERVER_DATA;
  3681. BASE_SERVER_STR_TO_LOCAL_STR(&tmpBaseWindowsDirectory, &tmpBaseStaticServerData->WindowsDirectory);
  3682. if ( uSize*2 < tmpBaseWindowsDirectory.MaximumLength ) {
  3683. return tmpBaseWindowsDirectory.MaximumLength/2;
  3684. }
  3685. RtlMoveMemory(
  3686. lpBuffer,
  3687. tmpBaseWindowsDirectory.Buffer,
  3688. tmpBaseWindowsDirectory.Length
  3689. );
  3690. lpBuffer[(tmpBaseWindowsDirectory.Length>>1)] = UNICODE_NULL;
  3691. return tmpBaseWindowsDirectory.Length/2;
  3692. }
  3693. #define ENUM_MAX_UILANG_SIZE 4 // max size (wchar) for UI langguage id in registry
  3694. #define NLS_CALL_ENUMPROC_BREAK_4( Locale, \
  3695. lpNlsEnumProc, \
  3696. dwFlags, \
  3697. pUnicodeBuffer, \
  3698. lParam) \
  3699. { \
  3700. if (((*((NLS_ENUMPROC4)lpNlsEnumProc))(pUnicodeBuffer, \
  3701. lParam)) != TRUE) \
  3702. { \
  3703. break; \
  3704. } \
  3705. }
  3706. #define NLS_CALL_ENUMPROC_TRUE_4( Locale, \
  3707. lpNlsEnumProc, \
  3708. dwFlags, \
  3709. pUnicodeBuffer, \
  3710. lParam) \
  3711. { \
  3712. if (((*((NLS_ENUMPROC4)lpNlsEnumProc))(pUnicodeBuffer, \
  3713. lParam)) != TRUE) \
  3714. { \
  3715. return (TRUE); \
  3716. } \
  3717. }
  3718. LANGID gSystemInstallLang; // system's original install language
  3719. LPWSTR FASTCALL EtwpNlsStrCpyW(
  3720. LPWSTR pwszDest,
  3721. LPCWSTR pwszSrc)
  3722. {
  3723. LPWSTR pwszRet = pwszDest; // ptr to beginning of string
  3724. loop:
  3725. if (!(pwszDest[0x0] = pwszSrc[0x0])) goto done;
  3726. if (!(pwszDest[0x1] = pwszSrc[0x1])) goto done;
  3727. if (!(pwszDest[0x2] = pwszSrc[0x2])) goto done;
  3728. if (!(pwszDest[0x3] = pwszSrc[0x3])) goto done;
  3729. if (!(pwszDest[0x4] = pwszSrc[0x4])) goto done;
  3730. if (!(pwszDest[0x5] = pwszSrc[0x5])) goto done;
  3731. if (!(pwszDest[0x6] = pwszSrc[0x6])) goto done;
  3732. if (!(pwszDest[0x7] = pwszSrc[0x7])) goto done;
  3733. if (!(pwszDest[0x8] = pwszSrc[0x8])) goto done;
  3734. if (!(pwszDest[0x9] = pwszSrc[0x9])) goto done;
  3735. if (!(pwszDest[0xA] = pwszSrc[0xA])) goto done;
  3736. if (!(pwszDest[0xB] = pwszSrc[0xB])) goto done;
  3737. if (!(pwszDest[0xC] = pwszSrc[0xC])) goto done;
  3738. if (!(pwszDest[0xD] = pwszSrc[0xD])) goto done;
  3739. if (!(pwszDest[0xE] = pwszSrc[0xE])) goto done;
  3740. if (!(pwszDest[0xF] = pwszSrc[0xF])) goto done;
  3741. pwszDest+= 0x10;
  3742. pwszSrc+= 0x10;
  3743. goto loop;
  3744. done:
  3745. return (pwszRet);
  3746. }
  3747. ULONG EtwpNlsConvertIntegerToString(
  3748. UINT Value,
  3749. UINT Base,
  3750. UINT Padding,
  3751. LPWSTR pResultBuf,
  3752. UINT Size)
  3753. {
  3754. UNICODE_STRING ObString; // value string
  3755. UINT ctr; // loop counter
  3756. LPWSTR pBufPtr; // ptr to result buffer
  3757. WCHAR pTmpBuf[MAX_PATH_LEN]; // ptr to temp buffer
  3758. ULONG rc = 0L; // return code
  3759. //
  3760. // Just to be safe we will check to see if the Size if less than
  3761. // the sizeof buffer we use on the stack.
  3762. //
  3763. if (Size > MAX_PATH_LEN) {
  3764. EtwpSetLastError(ERROR_BUFFER_OVERFLOW);
  3765. #if DBG
  3766. //
  3767. // If we hit this assert then, someone made a code change that
  3768. // busted the assumptions made in this routine. Either this routine
  3769. // or the caller needs to be modified.
  3770. //
  3771. EtwpAssert(FALSE);
  3772. #endif
  3773. return 0;
  3774. }
  3775. //
  3776. // Set up the Unicode string structure.
  3777. //
  3778. ObString.Length = (USHORT)(Size * sizeof(WCHAR));
  3779. ObString.MaximumLength = (USHORT)(Size * sizeof(WCHAR));
  3780. ObString.Buffer = pTmpBuf;
  3781. //
  3782. // Get the value as a string.
  3783. //
  3784. if (rc = RtlIntegerToUnicodeString(Value, Base, &ObString))
  3785. {
  3786. return (rc);
  3787. }
  3788. //
  3789. // Pad the string with the appropriate number of zeros.
  3790. //
  3791. pBufPtr = pResultBuf;
  3792. for (ctr = GET_WC_COUNT(ObString.Length);
  3793. ctr < Padding;
  3794. ctr++, pBufPtr++)
  3795. {
  3796. *pBufPtr = NLS_CHAR_ZERO;
  3797. }
  3798. EtwpNlsStrCpyW(pBufPtr, ObString.Buffer);
  3799. //
  3800. // Return success.
  3801. //
  3802. return (NO_ERROR);
  3803. }
  3804. LANGID WINAPI EtwpGetSystemDefaultUILanguage()
  3805. {
  3806. //
  3807. // Get the original install language and return it.
  3808. //
  3809. if (gSystemInstallLang == 0)
  3810. {
  3811. if (NtQueryInstallUILanguage(&gSystemInstallLang) != STATUS_SUCCESS)
  3812. {
  3813. gSystemInstallLang = 0;
  3814. return (NLS_DEFAULT_UILANG);
  3815. }
  3816. }
  3817. return (gSystemInstallLang);
  3818. }
  3819. BOOL EtwpInternal_EnumUILanguages(
  3820. NLS_ENUMPROC lpUILanguageEnumProc,
  3821. DWORD dwFlags,
  3822. LONG_PTR lParam)
  3823. {
  3824. PKEY_VALUE_FULL_INFORMATION pKeyValueFull = NULL;
  3825. BYTE pStatic[MAX_KEY_VALUE_FULLINFO];
  3826. LANGID LangID; // language id
  3827. WCHAR szLang[MAX_PATH]; // language id string
  3828. HANDLE hKey = NULL; // handle to muilang key
  3829. ULONG Index; // index for enumeration
  3830. ULONG ResultLength; // # bytes written
  3831. WCHAR wch; // first char of name
  3832. LPWSTR pName; // ptr to name string from registry
  3833. ULONG NameLen; // length of name string
  3834. ULONG rc = 0L; // return code
  3835. //
  3836. // Invalid Parameter Check:
  3837. // - function pointer is null
  3838. //
  3839. if (lpUILanguageEnumProc == NULL)
  3840. {
  3841. EtwpSetLastError(ERROR_INVALID_PARAMETER);
  3842. return (FALSE);
  3843. }
  3844. //
  3845. // Invalid Flags Check:
  3846. // - flags must be 0
  3847. //
  3848. if (dwFlags != 0)
  3849. {
  3850. EtwpSetLastError(ERROR_INVALID_FLAGS);
  3851. return (FALSE);
  3852. }
  3853. //
  3854. // Call the appropriate callback function with the user's UI
  3855. // language.
  3856. //
  3857. LangID = EtwpGetSystemDefaultUILanguage();
  3858. if (EtwpNlsConvertIntegerToString(LangID, 16, 4, szLang, MAX_PATH) == NO_ERROR)
  3859. {
  3860. NLS_CALL_ENUMPROC_TRUE_4( gSystemLocale,
  3861. lpUILanguageEnumProc,
  3862. dwFlags,
  3863. szLang,
  3864. lParam);
  3865. }
  3866. else
  3867. {
  3868. szLang[0] = 0;
  3869. }
  3870. //
  3871. // Open the MUILanguages registry key. It is acceptable if the key
  3872. // does not exist, so return TRUE as there are no items to enumerate.
  3873. //
  3874. if(hKey == NULL )
  3875. {
  3876. NTSTATUS st;
  3877. PWCHAR Buffer;
  3878. HRESULT hr;
  3879. Buffer = EtwpAlloc(DEFAULT_ALLOC_SIZE);
  3880. if (Buffer == NULL) {
  3881. #ifdef DBG
  3882. EtwpDebugPrint(("WMI: Failed to Allcate memory for Buffer in EtwpInternal_EnumUILanguages \n"));
  3883. #endif
  3884. EtwpSetLastError(STATUS_NO_MEMORY);
  3885. return (FALSE);
  3886. }
  3887. hr = StringCbPrintfW(Buffer, DEFAULT_ALLOC_SIZE, L"%ws\\%ws", NLS_HKLM_SYSTEM, NLS_MUILANG_KEY);
  3888. WmipAssert(hr == S_OK);
  3889. st = EtwpRegOpenKey(Buffer, &hKey);
  3890. EtwpFree(Buffer);
  3891. if(!NT_SUCCESS(st))
  3892. {
  3893. //
  3894. // If NLS key doesn't exist then it is not a failure as
  3895. // this means we just don't have any new languages
  3896. //
  3897. return TRUE;
  3898. }
  3899. }
  3900. //
  3901. // Loop through the MUILanguage ids in the registry, call the
  3902. // function pointer for each.
  3903. //
  3904. // End loop if either FALSE is returned from the callback function
  3905. // or the end of the list is reached.
  3906. //
  3907. Index = 0;
  3908. pKeyValueFull = (PKEY_VALUE_FULL_INFORMATION)pStatic;
  3909. RtlZeroMemory(pKeyValueFull, MAX_KEY_VALUE_FULLINFO);
  3910. rc = NtEnumerateValueKey( hKey,
  3911. Index,
  3912. KeyValueFullInformation,
  3913. pKeyValueFull,
  3914. MAX_KEY_VALUE_FULLINFO,
  3915. &ResultLength );
  3916. while (rc != STATUS_NO_MORE_ENTRIES)
  3917. {
  3918. if (!NT_SUCCESS(rc))
  3919. {
  3920. //
  3921. // If we get a different error, then the registry
  3922. // is corrupt. Just return FALSE.
  3923. //
  3924. KdPrint(("NLSAPI: MUI Languages Enumeration Error - registry corrupt. - %lx.\n",
  3925. rc));
  3926. EtwpSetLastError(ERROR_BADDB);
  3927. return (FALSE);
  3928. }
  3929. //
  3930. // Skip over any entry that does not have data associated with it.
  3931. //
  3932. pName = pKeyValueFull->Name;
  3933. wch = *pName;
  3934. NameLen = pKeyValueFull->NameLength / sizeof(WCHAR);
  3935. if ( (NameLen == ENUM_MAX_UILANG_SIZE) &&
  3936. (((wch >= NLS_CHAR_ZERO) && (wch <= NLS_CHAR_NINE)) ||
  3937. (((wch | 0x0020) >= L'a') && ((wch | 0x0020) <= L'f'))) &&
  3938. (pKeyValueFull->DataLength > 2) )
  3939. {
  3940. //
  3941. // Make sure the UI language is zero terminated.
  3942. //
  3943. pName[NameLen] = 0;
  3944. //
  3945. // Make sure it's not the same as the user UI language
  3946. // that we already enumerated.
  3947. //
  3948. if (wcscmp(szLang, pName) != 0)
  3949. {
  3950. //
  3951. // Call the appropriate callback function.
  3952. //
  3953. NLS_CALL_ENUMPROC_BREAK_4( gSystemLocale,
  3954. lpUILanguageEnumProc,
  3955. dwFlags,
  3956. pName,
  3957. lParam );
  3958. }
  3959. }
  3960. //
  3961. // Increment enumeration index value and get the next enumeration.
  3962. //
  3963. Index++;
  3964. RtlZeroMemory(pKeyValueFull, MAX_KEY_VALUE_FULLINFO);
  3965. rc = NtEnumerateValueKey( hKey,
  3966. Index,
  3967. KeyValueFullInformation,
  3968. pKeyValueFull,
  3969. MAX_KEY_VALUE_FULLINFO,
  3970. &ResultLength );
  3971. }
  3972. //
  3973. // Close the registry key.
  3974. //
  3975. CLOSE_REG_KEY(hKey);
  3976. //
  3977. // Return success.
  3978. //
  3979. return (TRUE);
  3980. }
  3981. BOOL EtwpEnumUILanguages(
  3982. UILANGUAGE_ENUMPROCW lpUILanguageEnumProc,
  3983. DWORD dwFlags,
  3984. LONG_PTR lParam)
  3985. {
  3986. return (EtwpInternal_EnumUILanguages( (NLS_ENUMPROC)lpUILanguageEnumProc,
  3987. dwFlags,
  3988. lParam));
  3989. }
  3990. ULONG EtwpAnsiToUnicode(
  3991. LPCSTR pszA,
  3992. LPWSTR * ppszW
  3993. ){
  3994. UNICODE_STRING DestinationString;
  3995. ANSI_STRING SourceString;
  3996. NTSTATUS Status;
  3997. BOOLEAN AllocateString;
  3998. ULONG UnicodeLength;
  3999. //
  4000. // If output is null then return error as we don't have
  4001. // any place to put output string
  4002. //
  4003. if(ppszW==NULL){
  4004. return(STATUS_INVALID_PARAMETER_2);
  4005. }
  4006. //
  4007. // If input is null then just return the same.
  4008. //
  4009. if (pszA == NULL)
  4010. {
  4011. *ppszW = NULL;
  4012. return(ERROR_SUCCESS);
  4013. }
  4014. //
  4015. // We ASSUME that if *ppszW!=NULL then we have sufficient
  4016. // amount of memory to copy
  4017. //
  4018. AllocateString = ((*ppszW) == NULL );
  4019. RtlInitAnsiString(&SourceString,(PCHAR)pszA);
  4020. UnicodeLength = RtlAnsiStringToUnicodeSize(&SourceString);
  4021. if ( UnicodeLength > MAXUSHORT ) {
  4022. return STATUS_INVALID_PARAMETER_1;
  4023. }
  4024. DestinationString.Length = (USHORT)(UnicodeLength - sizeof(UNICODE_NULL));
  4025. DestinationString.MaximumLength = (USHORT)UnicodeLength;
  4026. DestinationString.Buffer = EtwpAlloc(UnicodeLength);
  4027. if ( !DestinationString.Buffer ) {
  4028. return STATUS_NO_MEMORY;
  4029. }
  4030. Status = RtlAnsiStringToUnicodeString( &DestinationString, &SourceString, FALSE );
  4031. if( NT_SUCCESS(Status)) {
  4032. if(AllocateString){
  4033. *ppszW = DestinationString.Buffer;
  4034. } else {
  4035. memcpy((*ppszW),DestinationString.Buffer,UnicodeLength);
  4036. EtwpFree(DestinationString.Buffer);
  4037. }
  4038. } else {
  4039. EtwpFree(DestinationString.Buffer);
  4040. }
  4041. return Status;
  4042. }