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.

1507 lines
39 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. common.h
  5. Abstract:
  6. This file contains structures and functions used in Ntdll.dll and advapi32.dll
  7. --*/
  8. #define STRSAFE_NO_DEPRECATE
  9. #include <strsafe.h>
  10. #define EtwpNtStatusToDosError(Status) ((ULONG)((Status == STATUS_SUCCESS)?ERROR_SUCCESS:RtlNtStatusToDosError(Status)))
  11. #define DEFAULT_ALLOC_SIZE 4096
  12. #define MAXSTR 1024
  13. #if !defined (_NTDLLBUILD_)
  14. extern void EtwpCallHWConfig(ULONG Reason);
  15. #endif
  16. HANDLE EtwpWin32Event;
  17. __inline
  18. ULONG
  19. EtwpSetDosError(
  20. IN ULONG DosError
  21. )
  22. {
  23. #if defined (_NTDLLBUILD_)
  24. EtwpSetLastError(DosError);
  25. #else
  26. SetLastError(DosError);
  27. #endif
  28. return DosError;
  29. }
  30. #if defined (_NTDLLBUILD_)
  31. extern
  32. RTL_CRITICAL_SECTION UMLogCritSect;
  33. BOOLEAN EtwLocksInitialized = FALSE;
  34. #endif
  35. HINSTANCE DllInstanceHandle;
  36. extern HANDLE EtwpKMHandle;
  37. #if DBG
  38. #define MOFLISTSIZEGUESS 1
  39. BOOLEAN EtwpLoggingEnabled = FALSE;
  40. #else
  41. #define MOFLISTSIZEGUESS 10
  42. #endif
  43. #ifndef MEMPHIS
  44. RTL_CRITICAL_SECTION PMCritSect;
  45. HANDLE EtwpCBInProgressEvent = NULL;
  46. PVOID EtwpProcessHeap = NULL;
  47. HANDLE EtwpDeviceHandle;
  48. #else
  49. HANDLE PMMutex;
  50. #endif
  51. NTSTATUS EtwpInitializeDll(
  52. void
  53. )
  54. /*+++
  55. Routine Description:
  56. Arguments:
  57. Return Value:
  58. ---*/
  59. {
  60. #ifdef MEMPHIS
  61. NTSTATUS Status;
  62. OBJECT_ATTRIBUTES Obja;
  63. Status = NtCreateMutant(&PMMutex,
  64. MUTANT_ALL_ACCESS,
  65. BaseFormatObjectAttributes(&Obja, NULL, NULL)
  66. FALSE);
  67. if (! NT_SUCCESS(Status))
  68. {
  69. return(Status);
  70. }
  71. #else
  72. NTSTATUS Status;
  73. Status = RtlInitializeCriticalSection(&PMCritSect);
  74. if (! NT_SUCCESS(Status))
  75. {
  76. return(Status);
  77. }
  78. Status = NtCreateEvent(&EtwpCBInProgressEvent,
  79. EVENT_ALL_ACCESS,
  80. NULL,
  81. NotificationEvent,
  82. TRUE);
  83. if (! NT_SUCCESS(Status))
  84. {
  85. RtlDeleteCriticalSection(&PMCritSect); // Delete PMCritSec.
  86. return (Status);
  87. }
  88. #if defined (_NTDLLBUILD_)
  89. Status = RtlInitializeCriticalSection(&UMLogCritSect);
  90. if (! NT_SUCCESS(Status))
  91. {
  92. RtlDeleteCriticalSection(&PMCritSect); // Delete PMCritSec.
  93. NtClose(EtwpCBInProgressEvent);
  94. EtwpCBInProgressEvent = NULL;
  95. return(Status);
  96. }
  97. EtwLocksInitialized = TRUE;
  98. #endif
  99. #endif
  100. return(STATUS_SUCCESS);
  101. }
  102. void EtwpDeinitializeDll(
  103. void
  104. )
  105. /*+++
  106. Routine Description:
  107. Arguments:
  108. Return Value:
  109. ---*/
  110. {
  111. #ifdef MEMPHIS
  112. CloseHandle(PMMutex);
  113. #else
  114. #if defined (_NTDLLBUILD_)
  115. if(EtwLocksInitialized){
  116. EtwLocksInitialized = FALSE;
  117. #endif
  118. RtlDeleteCriticalSection(&PMCritSect);
  119. NtClose(EtwpCBInProgressEvent);
  120. EtwpCBInProgressEvent = NULL;
  121. #if defined (_NTDLLBUILD_)
  122. RtlDeleteCriticalSection(&UMLogCritSect);
  123. }
  124. #endif
  125. if ((EtwpProcessHeap != NULL) &&
  126. (EtwpProcessHeap != RtlProcessHeap()))
  127. {
  128. RtlDestroyHeap(EtwpProcessHeap);
  129. EtwpProcessHeap = NULL;
  130. }
  131. if (EtwpDeviceHandle != NULL)
  132. {
  133. #if defined (_NTDLLBUILD_)
  134. EtwpCloseHandle(EtwpDeviceHandle);
  135. #else
  136. CloseHandle(EtwpDeviceHandle);
  137. #endif
  138. EtwpDeviceHandle = NULL;
  139. }
  140. #endif
  141. if (EtwpWin32Event != NULL)
  142. {
  143. #if defined (_NTDLLBUILD_)
  144. EtwpCloseHandle(EtwpWin32Event);
  145. #else
  146. CloseHandle(EtwpWin32Event);
  147. #endif
  148. EtwpWin32Event = NULL;
  149. }
  150. }
  151. NTSTATUS
  152. EtwpRegOpenKey(
  153. IN PCWSTR lpKeyName,
  154. OUT PHANDLE KeyHandle
  155. )
  156. {
  157. OBJECT_ATTRIBUTES ObjectAttributes;
  158. UNICODE_STRING KeyName;
  159. RtlInitUnicodeString( &KeyName, lpKeyName );
  160. RtlZeroMemory(&ObjectAttributes, sizeof(OBJECT_ATTRIBUTES));
  161. InitializeObjectAttributes(
  162. &ObjectAttributes,
  163. &KeyName,
  164. OBJ_CASE_INSENSITIVE,
  165. NULL,
  166. NULL
  167. );
  168. return NtOpenKey( KeyHandle, KEY_READ, &ObjectAttributes );
  169. }
  170. NTSTATUS
  171. EtwpRegQueryValueKey(
  172. IN HANDLE KeyHandle,
  173. IN LPWSTR lpValueName,
  174. IN ULONG Length,
  175. OUT PVOID KeyValue,
  176. OUT PULONG ResultLength
  177. )
  178. {
  179. UNICODE_STRING ValueName;
  180. ULONG BufferLength;
  181. NTSTATUS Status;
  182. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
  183. RtlInitUnicodeString( &ValueName, lpValueName );
  184. BufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + Length;
  185. KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)
  186. RtlAllocateHeap (RtlProcessHeap(),0,BufferLength);
  187. if (KeyValueInformation == NULL) {
  188. return STATUS_NO_MEMORY;
  189. }
  190. Status = NtQueryValueKey(
  191. KeyHandle,
  192. &ValueName,
  193. KeyValuePartialInformation,
  194. KeyValueInformation,
  195. BufferLength,
  196. ResultLength
  197. );
  198. if (NT_SUCCESS(Status)) {
  199. RtlCopyMemory(KeyValue,
  200. KeyValueInformation->Data,
  201. KeyValueInformation->DataLength
  202. );
  203. *ResultLength = KeyValueInformation->DataLength;
  204. if (KeyValueInformation->Type == REG_SZ) {
  205. if (KeyValueInformation->DataLength + sizeof(WCHAR) > Length) {
  206. KeyValueInformation->DataLength -= sizeof(WCHAR);
  207. }
  208. ((PUCHAR)KeyValue)[KeyValueInformation->DataLength++] = 0;
  209. ((PUCHAR)KeyValue)[KeyValueInformation->DataLength] = 0;
  210. *ResultLength = KeyValueInformation->DataLength + sizeof(WCHAR);
  211. }
  212. }
  213. RtlFreeHeap(RtlProcessHeap(),0,KeyValueInformation);
  214. return Status;
  215. }
  216. #if DBG
  217. NTSTATUS EtwpGetRegistryValue(
  218. TCHAR *ValueName,
  219. PULONG Value
  220. )
  221. {
  222. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  223. ULONG DataLength;
  224. HANDLE Handle = INVALID_HANDLE_VALUE;
  225. Status = EtwpRegOpenKey(WmiRegKeyText, &Handle);
  226. if (NT_SUCCESS(Status)) {
  227. Status = EtwpRegQueryValueKey(Handle,
  228. ValueName,
  229. sizeof(DWORD),
  230. (PVOID)Value,
  231. &DataLength
  232. );
  233. NtClose(Handle);
  234. }
  235. return Status;
  236. }
  237. #endif
  238. BOOLEAN
  239. WmiDllInitialize(
  240. IN PVOID DllBase,
  241. IN ULONG Reason,
  242. IN PCONTEXT Context OPTIONAL
  243. )
  244. /*++
  245. Routine Description:
  246. This function implements Win32 base dll initialization.
  247. Arguments:
  248. DllHandle -
  249. Reason - attach\detach
  250. Context - Not Used
  251. Return Value:
  252. STATUS_SUCCESS
  253. --*/
  254. {
  255. //
  256. // NOTE : Do not use WMI heap in this function
  257. // or in any of the routines called subsequently
  258. // as WMI Heap is not initialized until any ETW API
  259. // is called.
  260. //
  261. NTSTATUS Status = STATUS_SUCCESS;
  262. ULONG Foo;
  263. DllInstanceHandle = (HINSTANCE)DllBase;
  264. if (Reason == DLL_PROCESS_ATTACH)
  265. {
  266. #if DBG
  267. Foo = EtwpLoggingEnabled ? 1 : 0;
  268. EtwpGetRegistryValue(LoggingEnableValueText,
  269. &Foo);
  270. EtwpLoggingEnabled = (Foo == 0) ? FALSE : TRUE;
  271. #endif
  272. Status = EtwpInitializeDll();
  273. } else if (Reason == DLL_PROCESS_DETACH) {
  274. //
  275. // Don't need to clean up if process is exiting
  276. //
  277. if (Context == NULL)
  278. {
  279. EtwpDeinitializeDll();
  280. }
  281. if (EtwpKMHandle != (HANDLE)NULL)
  282. {
  283. #if defined (_NTDLLBUILD_)
  284. EtwpCloseHandle(EtwpKMHandle);
  285. #else
  286. CloseHandle(EtwpKMHandle);
  287. #endif
  288. }
  289. }
  290. #if !defined (_NTDLLBUILD_)
  291. EtwpCallHWConfig(Reason);
  292. #endif
  293. return(NT_SUCCESS(Status));
  294. }
  295. #ifndef MEMPHIS
  296. VOID
  297. EtwpCreateHeap(
  298. void
  299. )
  300. {
  301. EtwpEnterPMCritSection();
  302. if (EtwpProcessHeap == NULL)
  303. {
  304. EtwpProcessHeap = RtlCreateHeap(HEAP_GROWABLE,
  305. NULL,
  306. DLLRESERVEDHEAPSIZE,
  307. DLLCOMMITHEAPSIZE,
  308. NULL,
  309. NULL);
  310. if (EtwpProcessHeap == NULL)
  311. {
  312. EtwpDebugPrint(("WMI: Cannot create EtwpProcessHeap, using process default\n"));
  313. EtwpProcessHeap = RtlProcessHeap();
  314. }
  315. }
  316. EtwpLeavePMCritSection();
  317. //
  318. // This has been copied to this function as in ntdll
  319. // we cannot execute WmiInitializeDll codepath. And
  320. // EtwpLoggingEnabled has to be checked only once.
  321. // So this place should be okay to initialze
  322. // EtwpLoggingEnabled
  323. //
  324. #if DBG && defined(_NTDLLBUILD_)
  325. {
  326. ULONG Foo;
  327. Foo = EtwpLoggingEnabled ? 1 : 0;
  328. EtwpGetRegistryValue(&LoggingEnableValueText, &Foo);
  329. EtwpLoggingEnabled = (Foo == 0) ? FALSE : TRUE;
  330. }
  331. #endif
  332. }
  333. #endif
  334. ULONG
  335. EtwpGetMofResourceList(
  336. PWMIMOFLIST *MofListPtr
  337. )
  338. {
  339. ULONG MofListSize;
  340. PWMIMOFLIST MofList;
  341. ULONG RetSize=0;
  342. ULONG Status;
  343. //
  344. // Make an intelligent guess as to the size needed to get all of
  345. // the MOF resources
  346. //
  347. *MofListPtr = NULL;
  348. MofListSize = MOFLISTSIZEGUESS * (sizeof(WMIMOFLIST) +
  349. (MAX_PATH +
  350. MAX_PATH) * sizeof(WCHAR));
  351. MofList = EtwpAlloc(MofListSize);
  352. if (MofList != NULL)
  353. {
  354. Status = EtwpSendWmiKMRequest(NULL,
  355. IOCTL_WMI_ENUMERATE_MOF_RESOURCES,
  356. NULL,
  357. 0,
  358. MofList,
  359. MofListSize,
  360. &RetSize,
  361. NULL);
  362. if ((Status == ERROR_SUCCESS) && (RetSize == sizeof(ULONG)))
  363. {
  364. //
  365. // The buffer was too small, but we now know how much we'll
  366. // need.
  367. //
  368. MofListSize = MofList->MofListCount;
  369. EtwpFree(MofList);
  370. MofList = EtwpAlloc(MofListSize);
  371. if (MofList != NULL)
  372. {
  373. //
  374. // Now lets retry the query
  375. //
  376. Status = EtwpSendWmiKMRequest(NULL,
  377. IOCTL_WMI_ENUMERATE_MOF_RESOURCES,
  378. NULL,
  379. 0,
  380. MofList,
  381. MofListSize,
  382. &RetSize,
  383. NULL);
  384. } else {
  385. Status = ERROR_NOT_ENOUGH_MEMORY;
  386. }
  387. }
  388. } else {
  389. Status = ERROR_NOT_ENOUGH_MEMORY;
  390. }
  391. if (Status == ERROR_SUCCESS)
  392. {
  393. if (RetSize >= sizeof(WMIMOFLIST))
  394. {
  395. *MofListPtr = MofList;
  396. } else {
  397. Status = ERROR_INVALID_PARAMETER;
  398. EtwpFree(MofList);
  399. }
  400. } else if (MofList != NULL) {
  401. EtwpFree(MofList);
  402. }
  403. return(Status);
  404. }
  405. PWCHAR EtwpRegistryToImagePath(
  406. PWCHAR ImagePath,
  407. PWCHAR RegistryPath
  408. )
  409. /*++
  410. Routine Description:
  411. This routine will determine the location of the device driver's image file
  412. from its registry path
  413. Arguments:
  414. RegistryPath is a pointer to the driver's registry path
  415. ImagePath is buffer of length MAX_PATH and returns the image path
  416. Return Value:
  417. pointer to Image path of driver or NULL if image path is unavailable
  418. --*/
  419. {
  420. #define SystemRoot TEXT("\\SystemRoot\\")
  421. #ifdef MEMPHIS
  422. #define SystemRootDirectory TEXT("%WinDir%\\")
  423. #else
  424. #define SystemRootDirectory TEXT("%SystemRoot%\\")
  425. #endif
  426. #define SystemRootCharSize (( sizeof(SystemRoot) / sizeof(WCHAR) ) - 1)
  427. #define DriversDirectory TEXT("\\System32\\Drivers\\")
  428. #define NdisDriversDirectory TEXT("\\System\\")
  429. #define QuestionPrefix TEXT("\\??\\")
  430. #define QuestionPrefixSize (( sizeof(QuestionPrefix) / sizeof(WCHAR) ) - 1)
  431. #define RegistryPrefix TEXT("\\Registry")
  432. HKEY RegKey;
  433. PWCHAR ImagePathPtr = NULL;
  434. ULONG ValueType;
  435. ULONG Size;
  436. PWCHAR DriverName;
  437. ULONG Len;
  438. BOOLEAN DefaultImageName;
  439. PWCHAR DriversDirectoryPath;
  440. WCHAR *Buffer;
  441. WCHAR *FullRegistryPath;
  442. WCHAR RegBuffer[DEFAULT_ALLOC_SIZE];
  443. Buffer = (PTCHAR)EtwpAlloc(2 * MAX_PATH * sizeof(WCHAR));
  444. if (Buffer != NULL)
  445. {
  446. FullRegistryPath = Buffer + MAX_PATH;
  447. //
  448. // Get the driver file name or the MOF image path from the KM
  449. // registry path. Here are the rules:
  450. //
  451. // 1. First check the MofImagePath value in the registry in case the
  452. // mof resource is in a different file from the driver.
  453. // 2. Next check the ImagePath value since the mof resource is assumed
  454. // to be part of the driver image.
  455. // 3. If no MofImagePath or ImagePath values then assume the mof resource
  456. // is in the driver file and compose the driver file name as
  457. // %SystemRoot%\System32\driver.sys.
  458. // 4. If MofImagePath or ImagePath was specified then
  459. // - Check first char for % or second character for :, or prefix
  460. // of \??\ and if so use EtwpExpandEnvironmentStringsW
  461. // - Check first part of path for \SystemRoot\, if so rebuild string
  462. // as %SystemRoot%\ and use ExpandEnvironementStrings
  463. // - Assume format D below and prepend %SystemRoot%\ and use
  464. // EtwpExpandEnvironmentStringsW
  465. // If MofImagePath or ImagePath value is present and it is a REG_EXPAND_SZ
  466. // then it is used to locate the file that holds the mof resource. It
  467. // can be in one of the following formats:
  468. // Format A - %SystemRoot%\System32\Foo.Dll
  469. // Format B -C:\WINNT\SYSTEM32\Drivers\Foo.SYS
  470. // Format C - \SystemRoot\System32\Drivers\Foo.SYS
  471. // Format D - System32\Drivers\Foo.Sys
  472. // Format E - \??\c:\foo.sys
  473. Len = wcslen(RegistryPath);
  474. if (Len > 0)
  475. {
  476. DriverName = RegistryPath + Len;
  477. while ((*(--DriverName) != '\\') && (--Len > 0)) ;
  478. }
  479. if (Len == 0)
  480. {
  481. EtwpDebugPrint(("WMI: Badly formed registry path %ws\n", RegistryPath));
  482. EtwpFree(Buffer);
  483. return(NULL);
  484. }
  485. DriverName++;
  486. StringCchCopyW(FullRegistryPath,
  487. MAX_PATH,
  488. TEXT("System\\CurrentControlSet\\Services\\"));
  489. StringCchCatW(FullRegistryPath,
  490. MAX_PATH,
  491. DriverName);
  492. DefaultImageName = TRUE;
  493. #if defined(_NTDLLBUILD_)
  494. StringCbPrintfW(RegBuffer,
  495. DEFAULT_ALLOC_SIZE,
  496. L"%ws\\%ws",
  497. L"\\REGISTRY\\MACHINE",
  498. FullRegistryPath);
  499. if (EtwpRegOpenKey(RegBuffer, &RegKey) == ERROR_SUCCESS)
  500. {
  501. ULONG cbSize;
  502. PKEY_VALUE_PARTIAL_INFORMATION Buf;
  503. Size = MAX_PATH * sizeof(WCHAR);
  504. cbSize = Size + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
  505. Buf = EtwpAlloc(cbSize);
  506. if( Buf ) {
  507. UNICODE_STRING UnicodeString;
  508. RtlInitUnicodeString(&UnicodeString, L"MofImagePath");
  509. if( NtQueryValueKey(RegKey,
  510. &UnicodeString,
  511. KeyValuePartialInformation,
  512. Buf,
  513. Size,
  514. &Size) == ERROR_SUCCESS)
  515. {
  516. RtlCopyMemory(ImagePath, &Buf->Data[0], Buf->DataLength);
  517. ValueType = Buf->Type;
  518. DefaultImageName = FALSE;
  519. } else {
  520. RtlInitUnicodeString(&UnicodeString, L"ImagePath");
  521. if( NtQueryValueKey(RegKey,
  522. &UnicodeString,
  523. KeyValuePartialInformation,
  524. Buf,
  525. Size,
  526. &Size) == ERROR_SUCCESS)
  527. {
  528. RtlCopyMemory(ImagePath, &Buf->Data[0], Buf->DataLength);
  529. ValueType = Buf->Type;
  530. DefaultImageName = FALSE;
  531. }
  532. }
  533. }
  534. EtwpFree(Buf);
  535. }
  536. #else
  537. if (RegOpenKey(HKEY_LOCAL_MACHINE,
  538. FullRegistryPath,
  539. &RegKey) == ERROR_SUCCESS)
  540. {
  541. Size = MAX_PATH * sizeof(WCHAR);
  542. if (RegQueryValueEx(RegKey,
  543. TEXT("MofImagePath"),
  544. NULL,
  545. &ValueType,
  546. (PBYTE)ImagePath,
  547. &Size) == ERROR_SUCCESS)
  548. {
  549. DefaultImageName = FALSE;
  550. } else {
  551. Size = MAX_PATH * sizeof(WCHAR);
  552. if (RegQueryValueEx(RegKey,
  553. TEXT("ImagePath"),
  554. NULL,
  555. &ValueType,
  556. (PBYTE)ImagePath,
  557. &Size) == ERROR_SUCCESS)
  558. {
  559. DefaultImageName = FALSE;
  560. }
  561. }
  562. NtClose(RegKey);
  563. }
  564. #endif
  565. if ((DefaultImageName) ||
  566. ((ValueType != REG_EXPAND_SZ) && (ValueType != REG_SZ)) ||
  567. (Size < (2 * sizeof(WCHAR))))
  568. {
  569. //
  570. // No special ImagePath or MofImagePath so assume image file is
  571. // %SystemRoot%\System32\Drivers\Driver.Sys
  572. StringCchCopyW(Buffer,
  573. MAX_PATH,
  574. TEXT("%SystemRoot%\\System32\\Drivers\\"));
  575. StringCchCatW(Buffer, MAX_PATH, DriverName);
  576. StringCchCatW(Buffer, MAX_PATH, TEXT(".SYS"));
  577. } else {
  578. if (_wcsnicmp(ImagePath,
  579. SystemRoot,
  580. SystemRootCharSize) == 0)
  581. {
  582. //
  583. // Looks like format C
  584. StringCchCopyW(Buffer, MAX_PATH, SystemRootDirectory);
  585. StringCchCatW(Buffer, MAX_PATH, &ImagePath[SystemRootCharSize]);
  586. } else if ((*ImagePath == '%') ||
  587. ( (Size > 3*sizeof(WCHAR)) && ImagePath[1] == TEXT(':')) )
  588. {
  589. //
  590. // Looks like format B or format A
  591. StringCchCopyW(Buffer, MAX_PATH, ImagePath);
  592. } else if (_wcsnicmp(ImagePath,
  593. QuestionPrefix,
  594. QuestionPrefixSize) == 0)
  595. {
  596. //
  597. // Looks like format E
  598. StringCchCopyW(Buffer, MAX_PATH, ImagePath+QuestionPrefixSize);
  599. } else {
  600. //
  601. // Assume format D
  602. StringCchCopyW(Buffer, MAX_PATH, SystemRootDirectory);
  603. StringCchCatW(Buffer, MAX_PATH, ImagePath);
  604. }
  605. }
  606. #if defined(_NTDLLBUILD_)
  607. Size = EtwpExpandEnvironmentStringsW(Buffer,
  608. ImagePath,
  609. MAX_PATH);
  610. #else
  611. Size = ExpandEnvironmentStrings(Buffer,
  612. ImagePath,
  613. MAX_PATH);
  614. #endif
  615. #ifdef MEMPHIS
  616. EtwpDebugPrint(("WMI: %s has mof in %s\n",
  617. DriverName, ImagePath));
  618. #else
  619. EtwpDebugPrint(("WMI: %ws has mof in %ws\n",
  620. DriverName, ImagePath));
  621. #endif
  622. EtwpFree(Buffer);
  623. } else {
  624. ImagePath = NULL;
  625. }
  626. return(ImagePath);
  627. }
  628. BOOLEAN
  629. EtwpCopyMRString(
  630. PWCHAR Buffer,
  631. ULONG BufferRemaining,
  632. PULONG BufferUsed,
  633. PWCHAR SourceString
  634. )
  635. {
  636. BOOLEAN BufferNotFull;
  637. ULONG len;
  638. len = wcslen(SourceString) + 1;
  639. if (len <= BufferRemaining)
  640. {
  641. wcscpy(Buffer, SourceString);
  642. *BufferUsed = len;
  643. BufferNotFull = TRUE;
  644. } else {
  645. BufferNotFull = FALSE;
  646. }
  647. return(BufferNotFull);
  648. }
  649. BOOLEAN
  650. EtwpFileExists(
  651. PWCHAR FileName
  652. )
  653. {
  654. HANDLE FindHandle;
  655. BOOLEAN Found;
  656. PWIN32_FIND_DATA FindData;
  657. FindData = (PWIN32_FIND_DATA)EtwpAlloc(sizeof(WIN32_FIND_DATA));
  658. if (FindData != NULL)
  659. {
  660. //
  661. // Now we need to make sure that the file a ctually exists
  662. //
  663. #if defined(_NTDLLBUILD_)
  664. FindHandle = EtwpFindFirstFileW(FileName, FindData);
  665. #else
  666. FindHandle = FindFirstFile(FileName, FindData);
  667. #endif
  668. if (FindHandle == INVALID_HANDLE_VALUE)
  669. {
  670. Found = FALSE;
  671. } else {
  672. #if defined(_NTDLLBUILD_)
  673. EtwpFindClose(FindHandle);
  674. #else
  675. FindClose(FindHandle);
  676. #endif
  677. Found = TRUE;
  678. }
  679. EtwpFree(FindData);
  680. } else {
  681. Found = FALSE;
  682. }
  683. return(Found);
  684. }
  685. ULONG EtwpGetWindowsDirectory(
  686. PWCHAR *s,
  687. PWCHAR Static,
  688. ULONG StaticSize
  689. )
  690. {
  691. ULONG Size;
  692. ULONG Status = ERROR_SUCCESS;
  693. #if defined(_NTDLLBUILD_)
  694. Size = EtwpGetSystemWindowsDirectoryW(Static, StaticSize);
  695. #else
  696. Size = GetWindowsDirectory(Static, StaticSize);
  697. #endif
  698. if (Size > StaticSize)
  699. {
  700. Size += sizeof(UNICODE_NULL);
  701. *s = EtwpAlloc(Size * sizeof(WCHAR));
  702. if (*s != NULL)
  703. {
  704. #if defined(_NTDLLBUILD_)
  705. Size = EtwpGetSystemWindowsDirectoryW(*s, Size);
  706. #else
  707. Size = GetWindowsDirectory(*s, Size);
  708. #endif
  709. } else {
  710. Status = ERROR_NOT_ENOUGH_MEMORY;
  711. }
  712. } else if (Size == 0) {
  713. #if defined(_NTDLLBUILD_)
  714. Status = EtwpGetLastError();
  715. #else
  716. Status = GetLastError();
  717. #endif
  718. } else {
  719. *s = Static;
  720. }
  721. if (Status == ERROR_SUCCESS)
  722. {
  723. if ( (*s)[Size-1] == L'\\')
  724. {
  725. (*s)[Size-1] = 0;
  726. }
  727. }
  728. return(Status);
  729. }
  730. ULONG
  731. EtwpBuildMUIPath(
  732. PWCHAR Buffer,
  733. ULONG BufferRemaining,
  734. PULONG BufferUsed,
  735. PWCHAR EnglishPath,
  736. PWCHAR Language,
  737. PBOOLEAN BufferNotFull
  738. )
  739. {
  740. #define FallbackDir L"\\MUI\\Fallback\\"
  741. #define MUIPath L"\\MUI\\"
  742. #define MUITail L".mui"
  743. ULONG EnglishLen;
  744. PWCHAR WinDir;
  745. PWCHAR s, p;
  746. ULONG len;
  747. ULONG Status, SizeNeeded;
  748. PWCHAR LanguagePath;
  749. PWCHAR WinDirStatic;
  750. ULONG WinDirStaticSize;
  751. WinDirStaticSize = MAX_PATH+1;
  752. WinDirStatic = EtwpAlloc(WinDirStaticSize * sizeof(WCHAR));
  753. if (WinDirStatic != NULL)
  754. {
  755. Status = ERROR_FILE_NOT_FOUND;
  756. LanguagePath = Buffer;
  757. EtwpDebugPrint(("WMI: Building MUI path for %ws in language %ws\n",
  758. EnglishPath, Language));
  759. EnglishLen = wcslen(EnglishPath);
  760. p = EnglishPath + EnglishLen;
  761. len = EnglishLen;
  762. //
  763. // Work from the end of the string to try to find the last \ so
  764. // we can then slip in the language name
  765. //
  766. while ( (len != 0) && (*p != L'\\'))
  767. {
  768. len--;
  769. p--;
  770. }
  771. if (len != 0)
  772. {
  773. p++;
  774. }
  775. EtwpDebugPrint(("WMI: Tail of %ws is %ws\n", EnglishPath, p));
  776. //
  777. // First try looking in <path>\\MUI\\<lang id> which is where 3rd
  778. // parties will install their resource only drivers. We look for
  779. // foo.sys and then foo.sys.mui.
  780. //
  781. SizeNeeded = len + wcslen(Language) + wcslen(MUIPath) + 1 + wcslen(p) + 1 + wcslen(MUITail);
  782. if (SizeNeeded <= BufferRemaining)
  783. {
  784. if (len != 0)
  785. {
  786. wcsncpy(LanguagePath, EnglishPath, len);
  787. LanguagePath[len] = 0;
  788. wcscat(LanguagePath, MUIPath);
  789. } else {
  790. LanguagePath[len] = 0;
  791. }
  792. wcscat(LanguagePath, Language);
  793. wcscat(LanguagePath, L"\\");
  794. wcscat(LanguagePath, p);
  795. if (EtwpFileExists(LanguagePath))
  796. {
  797. *BufferUsed = wcslen(LanguagePath) + 1;
  798. *BufferNotFull = TRUE;
  799. Status = ERROR_SUCCESS;
  800. EtwpDebugPrint(("WMI: #1 - Found %ws\n", LanguagePath));
  801. } else {
  802. wcscat(LanguagePath, MUITail);
  803. if (EtwpFileExists(LanguagePath))
  804. {
  805. *BufferUsed = wcslen(LanguagePath) + 1;
  806. *BufferNotFull = TRUE;
  807. Status = ERROR_SUCCESS;
  808. EtwpDebugPrint(("WMI: #2 - Found %ws\n", LanguagePath));
  809. }
  810. }
  811. } else {
  812. *BufferNotFull = FALSE;
  813. Status = ERROR_SUCCESS;
  814. }
  815. if (Status != ERROR_SUCCESS)
  816. {
  817. //
  818. // Next lets check the fallback directory,
  819. // %windir%\MUI\Fallback\<lang id>. This is where system components
  820. // are installed by default.
  821. //
  822. Status = EtwpGetWindowsDirectory(&WinDir,
  823. WinDirStatic,
  824. WinDirStaticSize);
  825. if (Status == ERROR_SUCCESS)
  826. {
  827. SizeNeeded = wcslen(WinDir) +
  828. wcslen(FallbackDir) +
  829. wcslen(Language) +
  830. 1 +
  831. wcslen(p) + 1 +
  832. wcslen(MUITail);
  833. if (SizeNeeded <= BufferRemaining)
  834. {
  835. wcscpy(LanguagePath, WinDir);
  836. wcscat(LanguagePath, FallbackDir);
  837. wcscat(LanguagePath, Language);
  838. wcscat(LanguagePath, L"\\");
  839. wcscat(LanguagePath, p);
  840. wcscat(LanguagePath, MUITail);
  841. if ( EtwpFileExists(LanguagePath))
  842. {
  843. *BufferUsed = wcslen(LanguagePath) + 1;
  844. *BufferNotFull = TRUE;
  845. Status = ERROR_SUCCESS;
  846. EtwpDebugPrint(("WMI: #3 - Found %ws\n", LanguagePath));
  847. } else {
  848. Status = ERROR_FILE_NOT_FOUND;
  849. }
  850. } else {
  851. *BufferNotFull = FALSE;
  852. Status = ERROR_SUCCESS;
  853. }
  854. if (WinDir != WinDirStatic)
  855. {
  856. EtwpFree(WinDir);
  857. }
  858. }
  859. }
  860. EtwpFree(WinDirStatic);
  861. } else {
  862. Status = ERROR_NOT_ENOUGH_MEMORY;
  863. }
  864. return(Status);
  865. }
  866. typedef struct
  867. {
  868. ULONG Count;
  869. ULONG MaxCount;
  870. PWCHAR *List;
  871. } ENUMLANGCTX, *PENUMLANGCTX;
  872. BOOL EnumUILanguageCallback(
  873. LPWSTR Language,
  874. LONG_PTR Context
  875. )
  876. {
  877. PENUMLANGCTX EnumLangCtx = (PENUMLANGCTX)Context;
  878. PWCHAR *p;
  879. PWCHAR w;
  880. ULONG NewMaxCount;
  881. if (EnumLangCtx->Count == EnumLangCtx->MaxCount)
  882. {
  883. NewMaxCount = EnumLangCtx->MaxCount * 2;
  884. p = EtwpAlloc( sizeof(PWCHAR) * NewMaxCount);
  885. if (p != NULL)
  886. {
  887. memset(p, 0, sizeof(PWCHAR) * NewMaxCount);
  888. memcpy(p, EnumLangCtx->List, EnumLangCtx->Count * sizeof(PWCHAR));
  889. EtwpFree(EnumLangCtx->List);
  890. EnumLangCtx->List = p;
  891. EnumLangCtx->MaxCount = NewMaxCount;
  892. } else {
  893. return(FALSE);
  894. }
  895. }
  896. w = EtwpAlloc( (wcslen(Language)+1) * sizeof(WCHAR) );
  897. if (w != NULL)
  898. {
  899. EnumLangCtx->List[EnumLangCtx->Count++] = w;
  900. wcscpy(w, Language);
  901. } else {
  902. return(FALSE);
  903. }
  904. return(TRUE);
  905. }
  906. ULONG
  907. EtwpGetLanguageList(
  908. PWCHAR **List,
  909. PULONG Count
  910. )
  911. {
  912. ENUMLANGCTX EnumLangCtx;
  913. BOOL b;
  914. ULONG Status;
  915. *List = NULL;
  916. *Count = 0;
  917. EnumLangCtx.Count = 0;
  918. EnumLangCtx.MaxCount = 8;
  919. EnumLangCtx.List = EtwpAlloc( 8 * sizeof(PWCHAR) );
  920. if (EnumLangCtx.List != NULL)
  921. {
  922. #if defined(_NTDLLBUILD_)
  923. b = EtwpEnumUILanguages(EnumUILanguageCallback,
  924. 0,
  925. (LONG_PTR)&EnumLangCtx);
  926. #else
  927. b = EnumUILanguages(EnumUILanguageCallback,
  928. 0,
  929. (LONG_PTR)&EnumLangCtx);
  930. #endif
  931. if (b)
  932. {
  933. *Count = EnumLangCtx.Count;
  934. *List = EnumLangCtx.List;
  935. Status = ERROR_SUCCESS;
  936. } else {
  937. if (EnumLangCtx.List != NULL)
  938. {
  939. EtwpFree(EnumLangCtx.List);
  940. }
  941. #if defined(_NTDLLBUILD_)
  942. Status = EtwpGetLastError();
  943. #else
  944. Status = GetLastError();
  945. #endif
  946. }
  947. } else {
  948. Status = ERROR_NOT_ENOUGH_MEMORY;
  949. }
  950. return(Status);
  951. }
  952. BOOL
  953. EtwpSynchReadFile(
  954. HANDLE LogFile,
  955. LPVOID Buffer,
  956. DWORD NumberOfBytesToRead,
  957. LPDWORD NumberOfBytesRead,
  958. LPOVERLAPPED Overlapped
  959. )
  960. /*++
  961. Routine Description:
  962. This routine performs synchronous read on a given file. Since logfile is opened for
  963. asychronous IO, current file position is not available. Thus, for synch read, we need
  964. to use this.
  965. Arguments:
  966. LogFile - handle to file
  967. Buffer - data buffer
  968. NumberOfBytesToRead - number of bytes to read
  969. NumberOfBytesRead - number of bytes read
  970. Overlapped - overlapped structure
  971. Returned Value:
  972. TRUE if succeeded.
  973. --*/
  974. {
  975. BOOL ReadSuccess;
  976. if (Overlapped == NULL || Overlapped->hEvent == NULL || Overlapped->hEvent == INVALID_HANDLE_VALUE) {
  977. return FALSE;
  978. }
  979. #if defined (_NTDLLBUILD_)
  980. if (!EtwpResetEvent(Overlapped->hEvent)) {
  981. return FALSE;
  982. }
  983. ReadSuccess = EtwpReadFile(LogFile,
  984. Buffer,
  985. NumberOfBytesToRead,
  986. NULL,
  987. Overlapped);
  988. if (ReadSuccess || EtwpGetLastError() == ERROR_IO_PENDING) {
  989. ReadSuccess = EtwpGetOverlappedResult(LogFile, Overlapped, NumberOfBytesRead, TRUE);
  990. if (!ReadSuccess && EtwpGetLastError() == ERROR_HANDLE_EOF) {
  991. *NumberOfBytesRead = 0;
  992. EtwpSetEvent(Overlapped->hEvent);
  993. }
  994. return ReadSuccess;
  995. }
  996. else {
  997. *NumberOfBytesRead = 0;
  998. EtwpSetEvent(Overlapped->hEvent);
  999. return FALSE;
  1000. }
  1001. #else
  1002. if (!ResetEvent(Overlapped->hEvent)) {
  1003. return FALSE;
  1004. }
  1005. ReadSuccess = ReadFile(LogFile,
  1006. Buffer,
  1007. NumberOfBytesToRead,
  1008. NULL,
  1009. Overlapped);
  1010. if (ReadSuccess || GetLastError() == ERROR_IO_PENDING) {
  1011. ReadSuccess = GetOverlappedResult(LogFile, Overlapped, NumberOfBytesRead, TRUE);
  1012. if (!ReadSuccess && GetLastError() == ERROR_HANDLE_EOF) {
  1013. *NumberOfBytesRead = 0;
  1014. SetEvent(Overlapped->hEvent);
  1015. }
  1016. return ReadSuccess;
  1017. }
  1018. else {
  1019. *NumberOfBytesRead = 0;
  1020. SetEvent(Overlapped->hEvent);
  1021. return FALSE;
  1022. }
  1023. #endif
  1024. }
  1025. PVOID
  1026. EtwpMemReserve(
  1027. IN SIZE_T Size
  1028. )
  1029. {
  1030. NTSTATUS Status;
  1031. PVOID lpAddress = NULL;
  1032. try {
  1033. Status = NtAllocateVirtualMemory(
  1034. NtCurrentProcess(),
  1035. &lpAddress,
  1036. 0,
  1037. &Size,
  1038. MEM_RESERVE,
  1039. PAGE_READWRITE);
  1040. }
  1041. except (EXCEPTION_EXECUTE_HANDLER) {
  1042. Status = GetExceptionCode();
  1043. }
  1044. if (NT_SUCCESS(Status)) {
  1045. return lpAddress;
  1046. }
  1047. else {
  1048. EtwpSetDosError(EtwpNtStatusToDosError(Status));
  1049. return NULL;
  1050. }
  1051. }
  1052. PVOID
  1053. EtwpMemCommit(
  1054. IN PVOID Buffer,
  1055. IN SIZE_T Size
  1056. )
  1057. {
  1058. NTSTATUS Status;
  1059. try {
  1060. Status = NtAllocateVirtualMemory(
  1061. NtCurrentProcess(),
  1062. &Buffer,
  1063. 0,
  1064. &Size,
  1065. MEM_COMMIT,
  1066. PAGE_READWRITE);
  1067. }
  1068. except (EXCEPTION_EXECUTE_HANDLER) {
  1069. Status = GetExceptionCode();
  1070. }
  1071. if (NT_SUCCESS(Status)) {
  1072. return Buffer;
  1073. }
  1074. else {
  1075. EtwpSetDosError(EtwpNtStatusToDosError(Status));
  1076. return NULL;
  1077. }
  1078. }
  1079. ULONG
  1080. EtwpMemFree(
  1081. IN PVOID Buffer
  1082. )
  1083. {
  1084. NTSTATUS Status;
  1085. SIZE_T Size = 0;
  1086. HANDLE hProcess = NtCurrentProcess();
  1087. if (Buffer == NULL) {
  1088. EtwpSetDosError(ERROR_INVALID_PARAMETER);
  1089. return FALSE;
  1090. }
  1091. try {
  1092. Status = NtFreeVirtualMemory( hProcess, &Buffer, &Size, MEM_RELEASE);
  1093. }
  1094. except (EXCEPTION_EXECUTE_HANDLER) {
  1095. Status = GetExceptionCode();
  1096. }
  1097. if (NT_SUCCESS(Status)) {
  1098. return TRUE;
  1099. }
  1100. else {
  1101. if (Status == STATUS_INVALID_PAGE_PROTECTION) {
  1102. if (RtlFlushSecureMemoryCache(Buffer, Size)) {
  1103. Status = NtFreeVirtualMemory(
  1104. hProcess, Buffer, &Size, MEM_RELEASE);
  1105. if (NT_SUCCESS(Status)) {
  1106. return TRUE;
  1107. }
  1108. }
  1109. }
  1110. EtwpSetDosError(EtwpNtStatusToDosError(Status));
  1111. return FALSE;
  1112. }
  1113. }
  1114. ULONG EtwpConvertWADToAnsi(
  1115. PWNODE_ALL_DATA Wnode
  1116. )
  1117. /*+++
  1118. Routine Description:
  1119. This routine will convert the instance names in a WNODE_ALL_DATA to
  1120. ansi. The conversion is done in place since we can assume that ansi
  1121. strings are no longer than unicode strings.
  1122. Arguments:
  1123. Wnode is the WNODE_ALL_DATA whose instance names are to be converted to
  1124. ANSI
  1125. Return Value:
  1126. Returns ERROR_SUCCESS or an error code.
  1127. ---*/
  1128. {
  1129. ULONG i;
  1130. ULONG Linkage;
  1131. ULONG InstanceCount;
  1132. PULONG InstanceNameOffsets;
  1133. PWCHAR Ptr;
  1134. ULONG Status = ERROR_SUCCESS;
  1135. EtwpAssert(!(Wnode->WnodeHeader.Flags & WNODE_FLAG_ANSI_INSTANCENAMES));
  1136. do
  1137. {
  1138. Wnode->WnodeHeader.Flags |= WNODE_FLAG_ANSI_INSTANCENAMES;
  1139. InstanceCount = Wnode->InstanceCount;
  1140. InstanceNameOffsets = (PULONG)(((PUCHAR)Wnode) +
  1141. Wnode->OffsetInstanceNameOffsets);
  1142. for (i = 0; i < InstanceCount; i++)
  1143. {
  1144. Ptr = (PWCHAR)(((PUCHAR)Wnode) + InstanceNameOffsets[i]);
  1145. try
  1146. {
  1147. Status = EtwpCountedUnicodeToCountedAnsi(Ptr, (PCHAR)Ptr);
  1148. } except(EXCEPTION_EXECUTE_HANDLER) {
  1149. // Wnode->WnodeHeader.Flags |= WNODE_FLAG_INVALID;
  1150. return(ERROR_SUCCESS);
  1151. }
  1152. if (Status != ERROR_SUCCESS)
  1153. {
  1154. #if defined (_NTDLLBUILD_)
  1155. EtwpSetLastError(Status);
  1156. #else
  1157. SetLastError(Status);
  1158. #endif
  1159. goto Done;
  1160. }
  1161. }
  1162. Linkage = Wnode->WnodeHeader.Linkage;
  1163. Wnode = (PWNODE_ALL_DATA)(((PUCHAR)Wnode) + Linkage);
  1164. } while (Linkage != 0);
  1165. Done:
  1166. return(Status);
  1167. }
  1168. ULONG EtwpUnicodeToAnsi(
  1169. LPCWSTR pszW,
  1170. LPSTR * ppszA,
  1171. ULONG *AnsiSizeInBytes OPTIONAL
  1172. ){
  1173. ANSI_STRING DestinationString;
  1174. UNICODE_STRING SourceString;
  1175. NTSTATUS Status;
  1176. BOOLEAN AllocateString;
  1177. ULONG AnsiLength;
  1178. //
  1179. // If output is null then return error as we don't have
  1180. // any place to put output string
  1181. //
  1182. if( ppszA==NULL ){
  1183. return(STATUS_INVALID_PARAMETER_2);
  1184. }
  1185. //
  1186. // If input is null then just return the same.
  1187. //
  1188. if (pszW == NULL)
  1189. {
  1190. *ppszA = NULL;
  1191. return(ERROR_SUCCESS);
  1192. }
  1193. //
  1194. // We ASSUME that if *ppszA!=NULL then we have sufficient
  1195. // amount of memory to copy
  1196. //
  1197. AllocateString = ((*ppszA) == NULL );
  1198. RtlInitUnicodeString(&SourceString,(LPWSTR)pszW);
  1199. AnsiLength = RtlUnicodeStringToAnsiSize(&SourceString);
  1200. if ( AnsiLength > MAXUSHORT ) {
  1201. return STATUS_INVALID_PARAMETER_1;
  1202. }
  1203. DestinationString.Length = (USHORT)(AnsiLength - 1);
  1204. DestinationString.MaximumLength = (USHORT)AnsiLength;
  1205. DestinationString.Buffer = EtwpAlloc(AnsiLength);
  1206. if ( DestinationString.Buffer == NULL ) {
  1207. return STATUS_NO_MEMORY;
  1208. }
  1209. Status = RtlUnicodeStringToAnsiString( &DestinationString, &SourceString, FALSE);
  1210. if( NT_SUCCESS(Status) ) {
  1211. if( AllocateString ) {
  1212. *ppszA = DestinationString.Buffer;
  1213. } else {
  1214. memcpy((*ppszA),DestinationString.Buffer,AnsiLength);
  1215. EtwpFree(DestinationString.Buffer);
  1216. }
  1217. if (AnsiSizeInBytes != NULL){
  1218. *AnsiSizeInBytes = DestinationString.Length;
  1219. }
  1220. } else {
  1221. EtwpFree(DestinationString.Buffer);
  1222. }
  1223. return Status;
  1224. }
  1225. ULONG EtwpCountedUnicodeToCountedAnsi(
  1226. PWCHAR Unicode,
  1227. PCHAR Ansi
  1228. )
  1229. /*++
  1230. Routine Description:
  1231. Translate a counted ansi string into a counted unicode string.
  1232. Conversion may be done inplace, that is Ansi == Unicode.
  1233. Arguments:
  1234. Unicode is the counted unicode string to convert to ansi
  1235. Ansi is the buffer to place the converted string into
  1236. Return Value:
  1237. ERROR_SUCCESS or an error code
  1238. --*/
  1239. {
  1240. PCHAR APtr;
  1241. PWCHAR WPtr;
  1242. ULONG AnsiSize, UnicodeSize;
  1243. ULONG Status;
  1244. UnicodeSize = *Unicode;
  1245. WPtr = EtwpAlloc(UnicodeSize + sizeof(WCHAR));
  1246. if (WPtr != NULL)
  1247. {
  1248. memcpy(WPtr, Unicode + 1, UnicodeSize);
  1249. WPtr[UnicodeSize/sizeof(WCHAR)] = UNICODE_NULL;
  1250. APtr = NULL;
  1251. Status = EtwpUnicodeToAnsi(WPtr, &APtr, &AnsiSize);
  1252. if (Status == ERROR_SUCCESS)
  1253. {
  1254. *((PUSHORT)Ansi) = (USHORT)AnsiSize;
  1255. memcpy(Ansi+sizeof(USHORT), APtr, AnsiSize);
  1256. Status = ERROR_SUCCESS;
  1257. EtwpFree(APtr);
  1258. }
  1259. EtwpFree(WPtr);
  1260. } else {
  1261. Status = ERROR_NOT_ENOUGH_MEMORY;
  1262. }
  1263. return(Status);
  1264. }