Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1508 lines
50 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. mofapi.c
  5. Abstract:
  6. WMI MOF access apis
  7. Author:
  8. 16-Jan-1997 AlanWar
  9. Revision History:
  10. --*/
  11. #include "wmiump.h"
  12. ULONG
  13. WMIAPI
  14. WmiMofEnumerateResourcesA(
  15. IN MOFHANDLE MofResourceHandle,
  16. OUT ULONG *MofResourceCount,
  17. OUT PMOFRESOURCEINFOA *MofResourceInfo
  18. )
  19. /*++
  20. Routine Description:
  21. ANSI thunk to WMIMofEnumerateResourcesA
  22. --*/
  23. {
  24. ULONG Status;
  25. PMOFRESOURCEINFOW MofResourceInfoUnicode;
  26. PMOFRESOURCEINFOA MofResourceInfoAnsi;
  27. PCHAR AnsiPtr;
  28. PCHAR Ansi;
  29. ULONG i, AnsiSize, AnsiStructureSize;
  30. ULONG MofResourceCountUnicode;
  31. ULONG AnsiLen;
  32. ULONG AnsiImagePathSize;
  33. ULONG AnsiResourceNameSize;
  34. WmipInitProcessHeap();
  35. Status = WmiMofEnumerateResourcesW(MofResourceHandle,
  36. &MofResourceCountUnicode,
  37. &MofResourceInfoUnicode);
  38. if (Status == ERROR_SUCCESS)
  39. {
  40. //
  41. // Walk the unicode MOFRESOURCEINFOW to determine the ansi size needed
  42. // for all of the ansi MOFRESOURCEINFOA structures and strings. We
  43. // determine the entire size and allocate a single block that holds
  44. // all of it since that is what WMIMofEnumerateResourceInfoW does.
  45. AnsiStructureSize = MofResourceCountUnicode * sizeof(MOFRESOURCEINFOA);
  46. AnsiSize = AnsiStructureSize;
  47. for (i = 0; i < MofResourceCountUnicode; i++)
  48. {
  49. Status = AnsiSizeForUnicodeString(MofResourceInfoUnicode[i].ImagePath,
  50. &AnsiImagePathSize);
  51. if (Status != ERROR_SUCCESS)
  52. {
  53. goto Done;
  54. }
  55. Status = AnsiSizeForUnicodeString(MofResourceInfoUnicode[i].ResourceName,
  56. &AnsiResourceNameSize);
  57. if (Status != ERROR_SUCCESS)
  58. {
  59. goto Done;
  60. }
  61. AnsiSize += AnsiImagePathSize + AnsiResourceNameSize;
  62. }
  63. MofResourceInfoAnsi = WmipAlloc(AnsiSize);
  64. if (MofResourceInfoAnsi != NULL)
  65. {
  66. AnsiPtr = (PCHAR)((PUCHAR)MofResourceInfoAnsi + AnsiStructureSize);
  67. for (i = 0; i < MofResourceCountUnicode; i++)
  68. {
  69. MofResourceInfoAnsi[i].ResourceSize = MofResourceInfoUnicode[i].ResourceSize;
  70. MofResourceInfoAnsi[i].ResourceBuffer = MofResourceInfoUnicode[i].ResourceBuffer;
  71. MofResourceInfoAnsi[i].ImagePath = AnsiPtr;
  72. Status = UnicodeToAnsi(MofResourceInfoUnicode[i].ImagePath,
  73. &MofResourceInfoAnsi[i].ImagePath,
  74. &AnsiLen);
  75. if (Status != ERROR_SUCCESS)
  76. {
  77. break;
  78. }
  79. AnsiPtr += AnsiLen;
  80. MofResourceInfoAnsi[i].ResourceName = AnsiPtr;
  81. Status = UnicodeToAnsi(MofResourceInfoUnicode[i].ResourceName,
  82. &MofResourceInfoAnsi[i].ResourceName,
  83. &AnsiLen);
  84. if (Status != ERROR_SUCCESS)
  85. {
  86. break;
  87. }
  88. AnsiPtr += AnsiLen;
  89. }
  90. if (Status == ERROR_SUCCESS)
  91. {
  92. try
  93. {
  94. *MofResourceInfo = MofResourceInfoAnsi;
  95. } except(EXCEPTION_EXECUTE_HANDLER) {
  96. Status = ERROR_NOACCESS;
  97. WmipFree(MofResourceInfoAnsi);
  98. }
  99. }
  100. } else {
  101. //
  102. // Not enough memory for ansi thunking so free unicode
  103. // mof class info and return an error.
  104. Status = ERROR_NOT_ENOUGH_MEMORY;
  105. }
  106. Done:
  107. WmiFreeBuffer(MofResourceInfoUnicode);
  108. }
  109. SetLastError(Status);
  110. return(Status);
  111. }
  112. PTCHAR WmipRegistryToImagePath(
  113. PTCHAR ImagePath,
  114. PTCHAR RegistryPath
  115. )
  116. /*++
  117. Routine Description:
  118. This routine will determine the location of the device driver's image file
  119. from its registry path
  120. Arguments:
  121. RegistryPath is a pointer to the driver's registry path
  122. ImagePath is buffer of length MAX_PATH and returns the image path
  123. Return Value:
  124. pointer to Image path of driver or NULL if image path is unavailable
  125. --*/
  126. {
  127. #define SystemRoot TEXT("\\SystemRoot\\")
  128. #ifdef MEMPHIS
  129. #define SystemRootDirectory TEXT("%WinDir%\\")
  130. #else
  131. #define SystemRootDirectory TEXT("%SystemRoot%\\")
  132. #endif
  133. #define SystemRootCharSize (( sizeof(SystemRoot) / sizeof(WCHAR) ) - 1)
  134. #define DriversDirectory TEXT("\\System32\\Drivers\\")
  135. #define NdisDriversDirectory TEXT("\\System\\")
  136. #define QuestionPrefix TEXT("\\??\\")
  137. #define QuestionPrefixSize (( sizeof(QuestionPrefix) / sizeof(WCHAR) ) - 1)
  138. #define RegistryPrefix TEXT("\\Registry")
  139. HKEY RegKey;
  140. PTCHAR ImagePathPtr = NULL;
  141. ULONG ValueType;
  142. ULONG Size;
  143. PTCHAR DriverName;
  144. ULONG Len;
  145. BOOLEAN DefaultImageName;
  146. PTCHAR DriversDirectoryPath;
  147. TCHAR *Buffer;
  148. TCHAR *FullRegistryPath;
  149. Buffer = (PTCHAR)WmipAlloc(2 * MAX_PATH * sizeof(TCHAR));
  150. if (Buffer != NULL)
  151. {
  152. FullRegistryPath = Buffer + MAX_PATH;
  153. #ifdef MEMPHIS
  154. TCHAR Buffer2[MAX_PATH];
  155. //
  156. // On memphis the registry path could point to two places
  157. // \Registry\Machine\System\CurrentControlSet\Services\Driver (Legacy)
  158. // System\CurrentControlSet\Services\Class\USB\0001
  159. if (_tcsnicmp(RegistryPath, RegistryPrefix, sizeof(RegistryPrefix)-1) != 0)
  160. {
  161. //
  162. // This is a non legacy type registry path.
  163. if (RegOpenKey(HKEY_LOCAL_MACHINE,
  164. RegistryPath,
  165. &RegKey) == ERROR_SUCCESS)
  166. {
  167. DriverName = Buffer2;
  168. Size = MAX_PATH * sizeof(WCHAR);
  169. if (RegQueryValueEx(RegKey,
  170. TEXT("NTMPDriver"),
  171. NULL,
  172. &ValueType,
  173. DriverName,
  174. &Size) == ERROR_SUCCESS)
  175. {
  176. DriversDirectoryPath = DriversDirectory;
  177. } else if (RegQueryValueEx(RegKey,
  178. TEXT("DeviceVxDs"),
  179. NULL,
  180. &ValueType,
  181. DriverName,
  182. &Size) == ERROR_SUCCESS)
  183. {
  184. DriversDirectoryPath = NdisDriversDirectory;
  185. } else {
  186. DriversDirectoryPath = NULL;
  187. }
  188. if ((DriversDirectoryPath != NULL) && (ValueType == REG_SZ))
  189. {
  190. Size = GetWindowsDirectory(Buffer, MAX_PATH);
  191. if ((Size != 0) &&
  192. (Size <= (MAX_PATH - _tcslen(DriverName) - sizeof(DriversDirectory) - 1)))
  193. {
  194. if (Buffer[Size-1] == TEXT('\\'))
  195. {
  196. Buffer[Size-1] = 0;
  197. }
  198. _tcscpy(ImagePath, Buffer);
  199. _tcscat(ImagePath, DriversDirectoryPath);
  200. _tcscat(ImagePath, DriverName);
  201. ImagePathPtr = ImagePath;
  202. RegCloseKey(RegKey);
  203. WmipFree(Buffer);
  204. return(ImagePathPtr);
  205. }
  206. }
  207. RegCloseKey(RegKey);
  208. }
  209. }
  210. #endif
  211. //
  212. // Get the driver file name or the MOF image path from the KM
  213. // registry path. Here are the rules:
  214. //
  215. // 1. First check the MofImagePath value in the registry in case the
  216. // mof resource is in a different file from the driver.
  217. // 2. Next check the ImagePath value since the mof resource is assumed
  218. // to be part of the driver image.
  219. // 3. If no MofImagePath or ImagePath values then assume the mof resource
  220. // is in the driver file and compose the driver file name as
  221. // %SystemRoot%\System32\driver.sys.
  222. // 4. If MofImagePath or ImagePath was specified then
  223. // - Check first char for % or second character for :, or prefix
  224. // of \??\ and if so use ExpandEnvironmentStrings
  225. // - Check first part of path for \SystemRoot\, if so rebuild string
  226. // as %SystemRoot%\ and use ExpandEnvironementStrings
  227. // - Assume format D below and prepend %SystemRoot%\ and use
  228. // ExpandEnvironmentStrings
  229. // If MofImagePath or ImagePath value is present and it is a REG_EXPAND_SZ
  230. // then it is used to locate the file that holds the mof resource. It
  231. // can be in one of the following formats:
  232. // Format A - %SystemRoot%\System32\Foo.Dll
  233. // Format B -C:\WINNT\SYSTEM32\Drivers\Foo.SYS
  234. // Format C - \SystemRoot\System32\Drivers\Foo.SYS
  235. // Format D - System32\Drivers\Foo.Sys
  236. // Format E - \??\c:\foo.sys
  237. Len = _tcslen(RegistryPath);
  238. if (Len > 0)
  239. {
  240. DriverName = RegistryPath + Len;
  241. while ((*(--DriverName) != '\\') && (--Len > 0)) ;
  242. }
  243. if (Len == 0)
  244. {
  245. WmipDebugPrint(("WMI: Badly formed registry path %ws\n", RegistryPath));
  246. WmipFree(Buffer);
  247. return(NULL);
  248. }
  249. DriverName++;
  250. _tcscpy(FullRegistryPath, TEXT("System\\CurrentControlSet\\Services\\"));
  251. _tcscat(FullRegistryPath, DriverName);
  252. DefaultImageName = TRUE;
  253. if (RegOpenKey(HKEY_LOCAL_MACHINE,
  254. FullRegistryPath,
  255. &RegKey) == ERROR_SUCCESS)
  256. {
  257. Size = MAX_PATH * sizeof(WCHAR);
  258. if (RegQueryValueEx(RegKey,
  259. TEXT("MofImagePath"),
  260. NULL,
  261. &ValueType,
  262. (PBYTE)ImagePath,
  263. &Size) == ERROR_SUCCESS)
  264. {
  265. DefaultImageName = FALSE;
  266. } else {
  267. Size = MAX_PATH * sizeof(WCHAR);
  268. if (RegQueryValueEx(RegKey,
  269. TEXT("ImagePath"),
  270. NULL,
  271. &ValueType,
  272. (PBYTE)ImagePath,
  273. &Size) == ERROR_SUCCESS)
  274. {
  275. DefaultImageName = FALSE;
  276. }
  277. }
  278. RegCloseKey(RegKey);
  279. }
  280. if ((DefaultImageName) ||
  281. ((ValueType != REG_EXPAND_SZ) && (ValueType != REG_SZ)) ||
  282. (Size < (2 * sizeof(WCHAR))))
  283. {
  284. //
  285. // No special ImagePath or MofImagePath so assume image file is
  286. // %SystemRoot%\System32\Drivers\Driver.Sys
  287. #ifdef MEMPHIS
  288. _tcscpy(Buffer, TEXT("%WinDir%\\System32\\Drivers\\"));
  289. #else
  290. _tcscpy(Buffer, TEXT("%SystemRoot%\\System32\\Drivers\\"));
  291. #endif
  292. _tcscat(Buffer, DriverName);
  293. _tcscat(Buffer, TEXT(".SYS"));
  294. } else {
  295. if (_tcsnicmp(ImagePath,
  296. SystemRoot,
  297. SystemRootCharSize) == 0)
  298. {
  299. //
  300. // Looks like format C
  301. _tcscpy(Buffer, SystemRootDirectory);
  302. _tcscat(Buffer, &ImagePath[SystemRootCharSize]);
  303. } else if ((*ImagePath == '%') ||
  304. ( (Size > 3*sizeof(WCHAR)) && ImagePath[1] == TEXT(':')) )
  305. {
  306. //
  307. // Looks like format B or format A
  308. _tcscpy(Buffer, ImagePath);
  309. } else if (_tcsnicmp(ImagePath,
  310. QuestionPrefix,
  311. QuestionPrefixSize) == 0)
  312. {
  313. //
  314. // Looks like format E
  315. _tcscpy(Buffer, ImagePath+QuestionPrefixSize);
  316. } else {
  317. //
  318. // Assume format D
  319. _tcscpy(Buffer, SystemRootDirectory);
  320. _tcscat(Buffer, ImagePath);
  321. }
  322. }
  323. Size = ExpandEnvironmentStrings(Buffer,
  324. ImagePath,
  325. MAX_PATH);
  326. #ifdef MEMPHIS
  327. WmipDebugPrint(("WMI: %s has mof in %s\n",
  328. DriverName, ImagePath));
  329. #else
  330. WmipDebugPrint(("WMI: %ws has mof in %ws\n",
  331. DriverName, ImagePath));
  332. #endif
  333. WmipFree(Buffer);
  334. } else {
  335. ImagePath = NULL;
  336. }
  337. return(ImagePath);
  338. }
  339. typedef struct
  340. {
  341. ULONG Count;
  342. ULONG MaxCount;
  343. PWCHAR *List;
  344. } ENUMLANGCTX, *PENUMLANGCTX;
  345. BOOL EnumUILanguageCallback(
  346. LPWSTR Language,
  347. LONG_PTR Context
  348. )
  349. {
  350. PENUMLANGCTX EnumLangCtx = (PENUMLANGCTX)Context;
  351. PWCHAR *p;
  352. PWCHAR w;
  353. ULONG NewMaxCount;
  354. if (EnumLangCtx->Count == EnumLangCtx->MaxCount)
  355. {
  356. NewMaxCount = EnumLangCtx->MaxCount * 2;
  357. p = WmipAlloc( sizeof(PWCHAR) * NewMaxCount);
  358. if (p != NULL)
  359. {
  360. memset(p, 0, sizeof(PWCHAR) * NewMaxCount);
  361. memcpy(p, EnumLangCtx->List, EnumLangCtx->Count * sizeof(PWCHAR));
  362. WmipFree(EnumLangCtx->List);
  363. EnumLangCtx->List = p;
  364. EnumLangCtx->MaxCount = NewMaxCount;
  365. } else {
  366. return(FALSE);
  367. }
  368. }
  369. w = WmipAlloc( (wcslen(Language)+1) * sizeof(WCHAR) );
  370. if (w != NULL)
  371. {
  372. EnumLangCtx->List[EnumLangCtx->Count++] = w;
  373. wcscpy(w, Language);
  374. } else {
  375. return(FALSE);
  376. }
  377. return(TRUE);
  378. }
  379. ULONG
  380. WmipGetLanguageList(
  381. PWCHAR **List,
  382. PULONG Count
  383. )
  384. {
  385. ENUMLANGCTX EnumLangCtx;
  386. BOOL b;
  387. ULONG Status;
  388. *List = NULL;
  389. *Count = 0;
  390. EnumLangCtx.Count = 0;
  391. EnumLangCtx.MaxCount = 8;
  392. EnumLangCtx.List = WmipAlloc( 8 * sizeof(PWCHAR) );
  393. if (EnumLangCtx.List != NULL)
  394. {
  395. b = EnumUILanguages(EnumUILanguageCallback,
  396. 0,
  397. (LONG_PTR)&EnumLangCtx);
  398. if (b)
  399. {
  400. *Count = EnumLangCtx.Count;
  401. *List = EnumLangCtx.List;
  402. Status = ERROR_SUCCESS;
  403. } else {
  404. if (EnumLangCtx.List != NULL)
  405. {
  406. WmipFree(EnumLangCtx.List);
  407. }
  408. Status = GetLastError();
  409. }
  410. } else {
  411. Status = ERROR_NOT_ENOUGH_MEMORY;
  412. }
  413. return(Status);
  414. }
  415. BOOLEAN
  416. WmipFileExists(
  417. PWCHAR FileName
  418. )
  419. {
  420. HANDLE FindHandle;
  421. BOOLEAN Found;
  422. PWIN32_FIND_DATA FindData;
  423. FindData = (PWIN32_FIND_DATA)WmipAlloc(sizeof(WIN32_FIND_DATA));
  424. if (FindData != NULL)
  425. {
  426. //
  427. // Now we need to make sure that the file a ctually exists
  428. //
  429. FindHandle = FindFirstFile(FileName,
  430. FindData);
  431. if (FindHandle == INVALID_HANDLE_VALUE)
  432. {
  433. Found = FALSE;
  434. } else {
  435. FindClose(FindHandle);
  436. Found = TRUE;
  437. }
  438. WmipFree(FindData);
  439. } else {
  440. Found = FALSE;
  441. }
  442. return(Found);
  443. }
  444. ULONG WmipGetWindowsDirectory(
  445. PWCHAR *s,
  446. PWCHAR Static,
  447. ULONG StaticSize
  448. )
  449. {
  450. ULONG Size;
  451. ULONG Status = ERROR_SUCCESS;
  452. Size = GetWindowsDirectory(Static, StaticSize);
  453. if (Size > StaticSize)
  454. {
  455. Size += sizeof(UNICODE_NULL);
  456. *s = WmipAlloc(Size * sizeof(WCHAR));
  457. if (*s != NULL)
  458. {
  459. Size = GetWindowsDirectory(*s, Size);
  460. } else {
  461. Status = ERROR_NOT_ENOUGH_MEMORY;
  462. }
  463. } else if (Size == 0) {
  464. Status = GetLastError();
  465. } else {
  466. *s = Static;
  467. }
  468. if (Status == ERROR_SUCCESS)
  469. {
  470. if ( (*s)[Size-1] == L'\\')
  471. {
  472. (*s)[Size-1] = 0;
  473. }
  474. }
  475. return(Status);
  476. }
  477. BOOLEAN
  478. WmipCopyMRString(
  479. PWCHAR Buffer,
  480. ULONG BufferRemaining,
  481. PULONG BufferUsed,
  482. PWCHAR SourceString
  483. )
  484. {
  485. BOOLEAN BufferNotFull;
  486. ULONG len;
  487. len = wcslen(SourceString) + 1;
  488. if (len <= BufferRemaining)
  489. {
  490. wcscpy(Buffer, SourceString);
  491. *BufferUsed = len;
  492. BufferNotFull = TRUE;
  493. } else {
  494. BufferNotFull = FALSE;
  495. }
  496. return(BufferNotFull);
  497. }
  498. BOOLEAN WmipCopyCountedString(
  499. PUCHAR Base,
  500. PULONG Offset,
  501. PULONG BufferRemaining,
  502. PWCHAR SourceString
  503. )
  504. {
  505. PWCHAR w;
  506. ULONG BufferUsed;
  507. ULONG BytesUsed;
  508. BOOLEAN BufferNotFull;
  509. if (*BufferRemaining > 1)
  510. {
  511. w = (PWCHAR)OffsetToPtr(Base, *Offset);
  512. (*BufferRemaining)--;
  513. BufferNotFull = WmipCopyMRString(w+1,
  514. *BufferRemaining,
  515. &BufferUsed,
  516. SourceString);
  517. if (BufferNotFull)
  518. {
  519. BytesUsed = BufferUsed * sizeof(WCHAR);
  520. *w = (USHORT)BytesUsed;
  521. (*BufferRemaining) -= BufferUsed;
  522. (*Offset) += BytesUsed + sizeof(USHORT);
  523. }
  524. } else {
  525. BufferNotFull = FALSE;
  526. }
  527. return(BufferNotFull);
  528. }
  529. ULONG
  530. WmipBuildMUIPath(
  531. PWCHAR Buffer,
  532. ULONG BufferRemaining,
  533. PULONG BufferUsed,
  534. PWCHAR EnglishPath,
  535. PWCHAR Language,
  536. PBOOLEAN BufferNotFull
  537. )
  538. {
  539. #define FallbackDir L"\\MUI\\Fallback\\"
  540. #define MUIPath L"\\MUI\\"
  541. #define MUITail L".mui"
  542. ULONG EnglishLen;
  543. PWCHAR WinDir;
  544. PWCHAR s, p;
  545. ULONG len;
  546. ULONG Status, SizeNeeded;
  547. PWCHAR LanguagePath;
  548. PWCHAR WinDirStatic;
  549. WinDirStatic = WmipAlloc((MAX_PATH+1) * sizeof(WCHAR));
  550. if (WinDirStatic != NULL)
  551. {
  552. Status = ERROR_FILE_NOT_FOUND;
  553. LanguagePath = Buffer;
  554. WmipDebugPrint(("WMI: Building MUI path for %ws in language %ws\n",
  555. EnglishPath, Language));
  556. EnglishLen = wcslen(EnglishPath);
  557. p = EnglishPath + EnglishLen;
  558. len = EnglishLen;
  559. //
  560. // Work from the end of the string to try to find the last \ so
  561. // we can then slip in the language name
  562. //
  563. while ( (len != 0) && (*p != L'\\'))
  564. {
  565. len--;
  566. p--;
  567. }
  568. if (len != 0)
  569. {
  570. p++;
  571. }
  572. WmipDebugPrint(("WMI: Tail of %ws is %ws\n", EnglishPath, p));
  573. //
  574. // First try looking in <path>\\MUI\\<lang id> which is where 3rd
  575. // parties will install their resource only drivers. We look for
  576. // foo.sys and then foo.sys.mui.
  577. //
  578. SizeNeeded = len + wcslen(Language) + wcslen(MUIPath) + 1 + wcslen(p) + 1 + wcslen(MUITail);
  579. if (SizeNeeded <= BufferRemaining)
  580. {
  581. if (len != 0)
  582. {
  583. wcsncpy(LanguagePath, EnglishPath, len);
  584. LanguagePath[len] = 0;
  585. wcscat(LanguagePath, MUIPath);
  586. } else {
  587. LanguagePath[len] = 0;
  588. }
  589. wcscat(LanguagePath, Language);
  590. wcscat(LanguagePath, L"\\");
  591. wcscat(LanguagePath, p);
  592. if (WmipFileExists(LanguagePath))
  593. {
  594. *BufferUsed = wcslen(LanguagePath) + 1;
  595. *BufferNotFull = TRUE;
  596. Status = ERROR_SUCCESS;
  597. WmipDebugPrint(("WMI: #1 - Found %ws\n", LanguagePath));
  598. } else {
  599. wcscat(LanguagePath, MUITail);
  600. if (WmipFileExists(LanguagePath))
  601. {
  602. *BufferUsed = wcslen(LanguagePath) + 1;
  603. *BufferNotFull = TRUE;
  604. Status = ERROR_SUCCESS;
  605. WmipDebugPrint(("WMI: #2 - Found %ws\n", LanguagePath));
  606. }
  607. }
  608. } else {
  609. *BufferNotFull = FALSE;
  610. Status = ERROR_SUCCESS;
  611. }
  612. if (Status != ERROR_SUCCESS)
  613. {
  614. //
  615. // Next lets check the fallback directory,
  616. // %windir%\MUI\Fallback\<lang id>. This is where system components
  617. // are installed by default.
  618. //
  619. Status = WmipGetWindowsDirectory(&WinDir,
  620. WinDirStatic,
  621. sizeof(WinDirStatic)/ sizeof(WCHAR));
  622. if (Status == ERROR_SUCCESS)
  623. {
  624. SizeNeeded = wcslen(WinDir) +
  625. wcslen(FallbackDir) +
  626. wcslen(Language) +
  627. 1 +
  628. wcslen(p) + 1 +
  629. wcslen(MUITail);
  630. if (SizeNeeded <= BufferRemaining)
  631. {
  632. wcscpy(LanguagePath, WinDir);
  633. wcscat(LanguagePath, FallbackDir);
  634. wcscat(LanguagePath, Language);
  635. wcscat(LanguagePath, L"\\");
  636. wcscat(LanguagePath, p);
  637. wcscat(LanguagePath, MUITail);
  638. if ( WmipFileExists(LanguagePath))
  639. {
  640. *BufferUsed = wcslen(LanguagePath) + 1;
  641. *BufferNotFull = TRUE;
  642. Status = ERROR_SUCCESS;
  643. WmipDebugPrint(("WMI: #3 - Found %ws\n", LanguagePath));
  644. } else {
  645. Status = ERROR_FILE_NOT_FOUND;
  646. }
  647. } else {
  648. *BufferNotFull = FALSE;
  649. Status = ERROR_SUCCESS;
  650. }
  651. if (WinDir != WinDirStatic)
  652. {
  653. WmipFree(WinDir);
  654. }
  655. }
  656. }
  657. WmipFree(WinDirStatic);
  658. } else {
  659. Status = ERROR_NOT_ENOUGH_MEMORY;
  660. }
  661. return(Status);
  662. }
  663. #if DBG
  664. #define MOFLISTSIZEGUESS 1
  665. #else
  666. #define MOFLISTSIZEGUESS 10
  667. #endif
  668. ULONG
  669. WmipGetMofResourceList(
  670. PWMIMOFLIST *MofListPtr
  671. )
  672. {
  673. ULONG MofListSize;
  674. PWMIMOFLIST MofList;
  675. ULONG RetSize;
  676. ULONG Status;
  677. //
  678. // Make an intelligent guess as to the size needed to get all of
  679. // the MOF resources
  680. //
  681. *MofListPtr = NULL;
  682. MofListSize = MOFLISTSIZEGUESS * (sizeof(WMIMOFLIST) +
  683. (MAX_PATH +
  684. MAX_PATH) * sizeof(WCHAR));
  685. MofList = WmipAlloc(MofListSize);
  686. if (MofList != NULL)
  687. {
  688. Status = WmipSendWmiKMRequest(NULL,
  689. IOCTL_WMI_ENUMERATE_MOF_RESOURCES,
  690. NULL,
  691. 0,
  692. MofList,
  693. MofListSize,
  694. &RetSize,
  695. NULL);
  696. if ((Status == ERROR_SUCCESS) && (RetSize == sizeof(ULONG)))
  697. {
  698. //
  699. // The buffer was too small, but we now know how much we'll
  700. // need.
  701. //
  702. MofListSize = MofList->MofListCount;
  703. WmipFree(MofList);
  704. MofList = WmipAlloc(MofListSize);
  705. if (MofList != NULL)
  706. {
  707. //
  708. // Now lets retry the query
  709. //
  710. Status = WmipSendWmiKMRequest(NULL,
  711. IOCTL_WMI_ENUMERATE_MOF_RESOURCES,
  712. NULL,
  713. 0,
  714. MofList,
  715. MofListSize,
  716. &RetSize,
  717. NULL);
  718. } else {
  719. Status = ERROR_NOT_ENOUGH_MEMORY;
  720. }
  721. }
  722. } else {
  723. Status = ERROR_NOT_ENOUGH_MEMORY;
  724. }
  725. if (Status == ERROR_SUCCESS)
  726. {
  727. if (RetSize >= sizeof(WMIMOFLIST))
  728. {
  729. *MofListPtr = MofList;
  730. } else {
  731. Status = ERROR_INVALID_PARAMETER;
  732. WmipFree(MofList);
  733. }
  734. } else if (MofList != NULL) {
  735. WmipFree(MofList);
  736. }
  737. return(Status);
  738. }
  739. ULONG
  740. WmiMofEnumerateResourcesW(
  741. IN MOFHANDLE MofResourceHandle,
  742. OUT ULONG *MofResourceCount,
  743. OUT PMOFRESOURCEINFOW *MofResourceInfo
  744. )
  745. /*++
  746. Routine Description:
  747. This routine will enumerate one or all of the MOF resources that are
  748. registered with WMI.
  749. Arguments:
  750. MofResourceHandle is reserved and must be 0
  751. *MofResourceCount returns with the count of MOFRESOURCEINFO structures
  752. returned in *MofResourceInfo.
  753. *MofResourceInfo returns with a pointer to an array of MOFRESOURCEINFO
  754. structures. The caller MUST call WMIFreeBuffer with *MofResourceInfo
  755. in order to ensure that there are no memory leaks.
  756. Return Value:
  757. ERROR_SUCCESS or an error code
  758. --*/
  759. {
  760. ULONG Status, SubStatus;
  761. PWMIMOFLIST MofList;
  762. ULONG MofListCount;
  763. ULONG MRInfoSize;
  764. ULONG MRCount;
  765. PWCHAR MRBuffer;
  766. PMOFRESOURCEINFOW MRInfo;
  767. PWCHAR RegPath, ResName, ImagePath;
  768. PWMIMOFENTRY MofEntry;
  769. ULONG i, j;
  770. PWCHAR *LanguageList;
  771. ULONG LanguageCount;
  772. BOOLEAN b;
  773. ULONG HeaderLen;
  774. ULONG MRBufferRemaining;
  775. PWCHAR ResourcePtr;
  776. ULONG BufferUsed;
  777. PWCHAR ImagePathStatic;
  778. WmipInitProcessHeap();
  779. if (MofResourceHandle != 0)
  780. {
  781. SetLastError(ERROR_INVALID_PARAMETER);
  782. return(ERROR_INVALID_PARAMETER);
  783. }
  784. ImagePathStatic = WmipAlloc(MAX_PATH * sizeof(WCHAR));
  785. if (ImagePathStatic != NULL)
  786. {
  787. *MofResourceInfo = NULL;
  788. Status = WmipGetMofResourceList(&MofList);
  789. if (Status == ERROR_SUCCESS)
  790. {
  791. //
  792. // Ok, we have got a valid list of mofs. Now we need to
  793. // loop over them all and convert the regpaths into image
  794. // paths
  795. //
  796. Status = WmipGetLanguageList(&LanguageList,
  797. &LanguageCount);
  798. if (Status == ERROR_SUCCESS)
  799. {
  800. MofListCount = MofList->MofListCount;
  801. //
  802. // Take a guess as to the size of the buffer needed to
  803. // satisfy the complete list of mof resources
  804. //
  805. HeaderLen = (MofListCount * (LanguageCount+1)) *
  806. sizeof(MOFRESOURCEINFOW);
  807. #if DBG
  808. MRInfoSize = HeaderLen + 2 * (MAX_PATH * sizeof(WCHAR));
  809. #else
  810. MRInfoSize = HeaderLen + (2*MofListCount * (MAX_PATH * sizeof(WCHAR)));
  811. #endif
  812. MRInfo = NULL;
  813. do
  814. {
  815. TryAgain:
  816. if (MRInfo != NULL)
  817. {
  818. WmipDebugPrint(("WMI: MofList was too small, retry 0x%x bytes\n",
  819. MRInfoSize));
  820. WmipFree(MRInfo);
  821. }
  822. MRInfo = WmipAlloc(MRInfoSize);
  823. if (MRInfo != NULL)
  824. {
  825. memset(MRInfo, 0, MRInfoSize);
  826. MRBuffer = (PWCHAR)OffsetToPtr(MRInfo, HeaderLen);
  827. MRBufferRemaining = (MRInfoSize - HeaderLen) / sizeof(WCHAR);
  828. MRCount = 0;
  829. for (i = 0; i < MofListCount; i++)
  830. {
  831. //
  832. // Pull out thee image path and resource names
  833. //
  834. MofEntry = &MofList->MofEntry[i];
  835. RegPath = (PWCHAR)OffsetToPtr(MofList, MofEntry->RegPathOffset);
  836. ResName = (PWCHAR)OffsetToPtr(MofList, MofEntry->ResourceOffset);
  837. if (*ResName != 0)
  838. {
  839. if ((MofEntry->Flags & WMIMOFENTRY_FLAG_USERMODE) == 0)
  840. {
  841. ImagePath = WmipRegistryToImagePath(ImagePathStatic,
  842. RegPath);
  843. } else {
  844. ImagePath = RegPath;
  845. }
  846. if (ImagePath != NULL)
  847. {
  848. //
  849. // If we've got a valid image path then
  850. // out it and the resource name into the
  851. // output buffer
  852. //
  853. MRInfo[MRCount].ImagePath = MRBuffer;
  854. b = WmipCopyMRString(MRBuffer,
  855. MRBufferRemaining,
  856. &BufferUsed,
  857. ImagePath);
  858. if (! b)
  859. {
  860. //
  861. // The buffer was not big enough so we
  862. // double the size used and try again
  863. //
  864. MRInfoSize *= 2;
  865. goto TryAgain;
  866. }
  867. MRBuffer += BufferUsed;
  868. MRBufferRemaining -= BufferUsed;
  869. WmipDebugPrint(("WMI: Add ImagePath %p (%ws) to MRList at position %d\n",
  870. MRInfo[MRCount].ImagePath,
  871. MRInfo[MRCount].ImagePath,
  872. MRCount));
  873. MRInfo[MRCount].ResourceName = MRBuffer;
  874. ResourcePtr = MRBuffer;
  875. WmipCopyMRString(MRBuffer,
  876. MRBufferRemaining,
  877. &BufferUsed,
  878. ResName);
  879. if (! b)
  880. {
  881. //
  882. // The buffer was not big enough so we
  883. // double the size used and try again
  884. //
  885. MRInfoSize *= 2;
  886. goto TryAgain;
  887. }
  888. MRBuffer += BufferUsed;
  889. MRBufferRemaining -= BufferUsed;
  890. WmipDebugPrint(("WMI: Add Resource %p (%ws) to MRList at position %d\n",
  891. MRInfo[MRCount].ResourceName,
  892. MRInfo[MRCount].ResourceName,
  893. MRCount));
  894. MRCount++;
  895. for (j = 0; j < LanguageCount; j++)
  896. {
  897. MRInfo[MRCount].ImagePath = MRBuffer;
  898. SubStatus = WmipBuildMUIPath(MRBuffer,
  899. MRBufferRemaining,
  900. &BufferUsed,
  901. ImagePath,
  902. LanguageList[j],
  903. &b);
  904. if (SubStatus == ERROR_SUCCESS)
  905. {
  906. if (! b)
  907. {
  908. //
  909. // The buffer was not big enough so we
  910. // double the size used and try again
  911. //
  912. MRInfoSize *= 2;
  913. goto TryAgain;
  914. }
  915. MRBuffer += BufferUsed;
  916. MRBufferRemaining -= BufferUsed;
  917. WmipDebugPrint(("WMI: Add ImagePath %p (%ws) to MRList at position %d\n",
  918. MRInfo[MRCount].ImagePath,
  919. MRInfo[MRCount].ImagePath,
  920. MRCount));
  921. //
  922. // We did find a MUI resource
  923. // so add it to the list
  924. //
  925. MRInfo[MRCount].ResourceName = ResourcePtr;
  926. WmipDebugPrint(("WMI: Add Resource %p (%ws) to MRList at position %d\n",
  927. MRInfo[MRCount].ResourceName,
  928. MRInfo[MRCount].ResourceName,
  929. MRCount));
  930. MRCount++;
  931. }
  932. }
  933. }
  934. }
  935. }
  936. } else {
  937. Status = STATUS_INSUFFICIENT_RESOURCES;
  938. }
  939. } while (FALSE);
  940. //
  941. // Free up memory used to hold the language list
  942. //
  943. for (i = 0; i < LanguageCount; i++)
  944. {
  945. WmipFree(LanguageList[i]);
  946. }
  947. WmipFree(LanguageList);
  948. *MofResourceCount = MRCount;
  949. *MofResourceInfo = MRInfo;
  950. }
  951. WmipFree(MofList);
  952. }
  953. WmipFree(ImagePathStatic);
  954. } else {
  955. Status = ERROR_NOT_ENOUGH_MEMORY;
  956. }
  957. SetLastError(Status);
  958. return(Status);
  959. }
  960. ULONG WmipBuildMofAddRemoveEvent(
  961. IN PWNODE_SINGLE_INSTANCE WnodeSI,
  962. IN PWMIMOFLIST MofList,
  963. IN PWCHAR *LanguageList,
  964. IN ULONG LanguageCount,
  965. IN BOOLEAN IncludeNeutralLanguage,
  966. IN NOTIFICATIONCALLBACK Callback,
  967. IN ULONG_PTR DeliveryContext,
  968. IN BOOLEAN IsAnsi
  969. )
  970. {
  971. PWNODE_ALL_DATA WnodeAD;
  972. ULONG BytesUsed, BufferUsed;
  973. BOOLEAN BufferNotFull;
  974. PWCHAR RegPath, ImagePath, ResourceName;
  975. ULONG SizeNeeded;
  976. ULONG InstanceCount, MaxInstanceCount;
  977. ULONG Status;
  978. ULONG Offset;
  979. POFFSETINSTANCEDATAANDLENGTH DataLenPtr;
  980. PWCHAR w;
  981. PULONG InstanceNamesOffsets;
  982. PWCHAR InstanceNames;
  983. ULONG BufferRemaining;
  984. ULONG i,j;
  985. PWMIMOFENTRY MofEntry;
  986. PWCHAR ImagePathStatic;
  987. WmipAssert(WnodeSI->WnodeHeader.Flags & WNODE_FLAG_SINGLE_INSTANCE);
  988. ImagePathStatic = WmipAlloc(MAX_PATH * sizeof(WCHAR));
  989. if (ImagePathStatic != NULL)
  990. {
  991. //
  992. // Figure out how large the WNODE_ALL_DATA will need to be and
  993. // guess at how much space to allocate for the image paths and
  994. // resource names
  995. //
  996. if (IncludeNeutralLanguage)
  997. {
  998. MaxInstanceCount = (LanguageCount + 1);
  999. } else {
  1000. MaxInstanceCount = LanguageCount;
  1001. }
  1002. MaxInstanceCount *= MofList->MofListCount;
  1003. #if DBG
  1004. SizeNeeded = sizeof(WNODE_ALL_DATA) +
  1005. (MaxInstanceCount *
  1006. (sizeof(ULONG) + // offset to instance name
  1007. sizeof(USHORT) + // instance name length
  1008. sizeof(OFFSETINSTANCEDATAANDLENGTH))) +
  1009. 64;
  1010. #else
  1011. SizeNeeded = sizeof(WNODE_ALL_DATA) +
  1012. (MaxInstanceCount *
  1013. (sizeof(ULONG) + // offset to instance name
  1014. sizeof(USHORT) + // instance name length
  1015. sizeof(OFFSETINSTANCEDATAANDLENGTH))) +
  1016. 0x1000;
  1017. #endif
  1018. WnodeAD = NULL;
  1019. do
  1020. {
  1021. TryAgain:
  1022. if (WnodeAD != NULL)
  1023. {
  1024. WmipFree(WnodeAD);
  1025. }
  1026. WnodeAD = WmipAlloc(SizeNeeded);
  1027. if (WnodeAD != NULL)
  1028. {
  1029. //
  1030. // Build up WNODE_ALL_DATA with all mof resources
  1031. //
  1032. memset(WnodeAD, 0, SizeNeeded);
  1033. WnodeAD->WnodeHeader = WnodeSI->WnodeHeader;
  1034. WnodeAD->WnodeHeader.Flags = WNODE_FLAG_ALL_DATA |
  1035. WNODE_FLAG_EVENT_ITEM;
  1036. WnodeAD->WnodeHeader.BufferSize = SizeNeeded;
  1037. WnodeAD->WnodeHeader.Linkage = 0;
  1038. //
  1039. // Establish pointer to the data offset and length
  1040. // structure and allocate space for all instances
  1041. //
  1042. Offset = FIELD_OFFSET(WNODE_ALL_DATA,
  1043. OffsetInstanceDataAndLength);
  1044. DataLenPtr = (POFFSETINSTANCEDATAANDLENGTH)OffsetToPtr(WnodeAD,
  1045. Offset);
  1046. Offset = (Offset +
  1047. (MaxInstanceCount *
  1048. sizeof(OFFSETINSTANCEDATAANDLENGTH)) + 7) & ~7;
  1049. //
  1050. // Establish the instance name offsets and fill in
  1051. // the empty instance names. Note we point them all
  1052. // to the same offset which is an empty instance
  1053. // name.
  1054. //
  1055. InstanceNamesOffsets = (PULONG)OffsetToPtr(WnodeAD,
  1056. Offset);
  1057. WnodeAD->OffsetInstanceNameOffsets = Offset;
  1058. Offset = Offset + (MaxInstanceCount * sizeof(ULONG));
  1059. InstanceNames = (PWCHAR)OffsetToPtr(WnodeAD, Offset);
  1060. *InstanceNames = 0;
  1061. for (i = 0; i < MaxInstanceCount; i++)
  1062. {
  1063. InstanceNamesOffsets[i] = Offset;
  1064. }
  1065. //
  1066. // Establish a pointer to the data block for all of
  1067. // the instances
  1068. //
  1069. Offset = (Offset +
  1070. (MaxInstanceCount * sizeof(USHORT)) + 7) & ~7;
  1071. WnodeAD->DataBlockOffset = Offset;
  1072. BufferRemaining = (SizeNeeded - Offset) / sizeof(WCHAR);
  1073. InstanceCount = 0;
  1074. //
  1075. // Loop over all mof resources in list
  1076. //
  1077. for (j = 0; j < MofList->MofListCount; j++)
  1078. {
  1079. MofEntry = &MofList->MofEntry[j];
  1080. RegPath = (PWCHAR)OffsetToPtr(MofList,
  1081. MofEntry->RegPathOffset);
  1082. //
  1083. // Convert regpath to image path if needed
  1084. //
  1085. if ((MofEntry->Flags & WMIMOFENTRY_FLAG_USERMODE) == 0)
  1086. {
  1087. ImagePath = WmipRegistryToImagePath(ImagePathStatic,
  1088. RegPath+1);
  1089. } else {
  1090. ImagePath = RegPath;
  1091. }
  1092. if (ImagePath != NULL)
  1093. {
  1094. ResourceName = (PWCHAR)OffsetToPtr(MofList,
  1095. MofEntry->ResourceOffset);
  1096. //
  1097. // Now lets go and build up the data for each
  1098. // instance. First fill in the language neutral mof
  1099. // if we are supposed to
  1100. //
  1101. if (IncludeNeutralLanguage)
  1102. {
  1103. DataLenPtr[InstanceCount].OffsetInstanceData = Offset;
  1104. if ((! WmipCopyCountedString((PUCHAR)WnodeAD,
  1105. &Offset,
  1106. &BufferRemaining,
  1107. ImagePath)) ||
  1108. (! WmipCopyCountedString((PUCHAR)WnodeAD,
  1109. &Offset,
  1110. &BufferRemaining,
  1111. ResourceName)))
  1112. {
  1113. SizeNeeded *=2;
  1114. goto TryAgain;
  1115. }
  1116. DataLenPtr[InstanceCount].LengthInstanceData = Offset -
  1117. DataLenPtr[InstanceCount].OffsetInstanceData;
  1118. InstanceCount++;
  1119. //
  1120. // We cheat here and do not align the offset on an
  1121. // 8 byte boundry for the next data block since we
  1122. // know the data type is a WCHAR and we know we are
  1123. // on a 2 byte boundry.
  1124. //
  1125. }
  1126. //
  1127. // Now loop over and build language specific mof
  1128. // resources
  1129. //
  1130. for (i = 0; i < LanguageCount; i++)
  1131. {
  1132. DataLenPtr[InstanceCount].OffsetInstanceData = Offset;
  1133. if (BufferRemaining > 1)
  1134. {
  1135. w = (PWCHAR)OffsetToPtr(WnodeAD, Offset);
  1136. Status = WmipBuildMUIPath(w+1,
  1137. BufferRemaining - 1,
  1138. &BufferUsed,
  1139. ImagePath,
  1140. LanguageList[i],
  1141. &BufferNotFull);
  1142. if (Status == ERROR_SUCCESS)
  1143. {
  1144. if (BufferNotFull)
  1145. {
  1146. BufferRemaining--;
  1147. BytesUsed = BufferUsed * sizeof(WCHAR);
  1148. *w = (USHORT)BytesUsed;
  1149. BufferRemaining -= BufferUsed;
  1150. Offset += (BytesUsed + sizeof(USHORT));
  1151. if (! WmipCopyCountedString((PUCHAR)WnodeAD,
  1152. &Offset,
  1153. &BufferRemaining,
  1154. ResourceName))
  1155. {
  1156. SizeNeeded *=2;
  1157. goto TryAgain;
  1158. }
  1159. DataLenPtr[InstanceCount].LengthInstanceData = Offset - DataLenPtr[InstanceCount].OffsetInstanceData;
  1160. //
  1161. // We cheat here and do not align the offset on an
  1162. // 8 byte boundry for the next data block since we
  1163. // know the data type is a WCHAR and we know we are
  1164. // on a 2 byte boundry.
  1165. //
  1166. InstanceCount++;
  1167. } else {
  1168. SizeNeeded *=2;
  1169. goto TryAgain;
  1170. }
  1171. }
  1172. } else {
  1173. SizeNeeded *=2;
  1174. goto TryAgain;
  1175. }
  1176. }
  1177. }
  1178. }
  1179. } else {
  1180. Status = ERROR_NOT_ENOUGH_MEMORY;
  1181. }
  1182. } while (FALSE);
  1183. if (WnodeAD != NULL)
  1184. {
  1185. WnodeAD->InstanceCount = InstanceCount;
  1186. WmipMakeEventCallbacks((PWNODE_HEADER)WnodeAD,
  1187. Callback,
  1188. DeliveryContext,
  1189. IsAnsi);
  1190. WmipFree(WnodeAD);
  1191. Status = ERROR_SUCCESS;
  1192. }
  1193. WmipFree(ImagePathStatic);
  1194. } else {
  1195. Status = ERROR_NOT_ENOUGH_MEMORY;
  1196. }
  1197. return(Status);
  1198. }
  1199. void WmipProcessMofAddRemoveEvent(
  1200. IN PWNODE_SINGLE_INSTANCE WnodeSI,
  1201. IN NOTIFICATIONCALLBACK Callback,
  1202. IN ULONG_PTR DeliveryContext,
  1203. IN BOOLEAN IsAnsi
  1204. )
  1205. {
  1206. PWCHAR RegPath, ResourceName;
  1207. PWCHAR *LanguageList;
  1208. ULONG LanguageCount;
  1209. ULONG Status;
  1210. PWMIMOFLIST MofList;
  1211. ULONG i;
  1212. PWMIMOFENTRY MofEntry;
  1213. ULONG Offset;
  1214. ULONG SizeNeeded;
  1215. PWCHAR w;
  1216. RegPath = (PWCHAR)OffsetToPtr(WnodeSI, WnodeSI->DataBlockOffset);
  1217. WmipAssert(*RegPath != 0);
  1218. ResourceName = (PWCHAR)OffsetToPtr(WnodeSI,
  1219. WnodeSI->DataBlockOffset +
  1220. sizeof(USHORT) +
  1221. *RegPath++ +
  1222. sizeof(USHORT));
  1223. SizeNeeded = sizeof(WMIMOFLIST) + ((wcslen(RegPath) +
  1224. (wcslen(ResourceName) + 2)) * sizeof(WCHAR));
  1225. MofList = (PWMIMOFLIST)WmipAlloc(SizeNeeded);
  1226. if (MofList != NULL)
  1227. {
  1228. Status = WmipGetLanguageList(&LanguageList,
  1229. &LanguageCount);
  1230. if (Status == ERROR_SUCCESS)
  1231. {
  1232. MofList->MofListCount = 1;
  1233. MofEntry = &MofList->MofEntry[0];
  1234. Offset = sizeof(WMIMOFLIST);
  1235. MofEntry->RegPathOffset = Offset;
  1236. w = (PWCHAR)OffsetToPtr(MofList, Offset);
  1237. wcscpy(w, RegPath);
  1238. Offset += (wcslen(RegPath) + 1) * sizeof(WCHAR);
  1239. MofEntry->ResourceOffset = Offset;
  1240. w = (PWCHAR)OffsetToPtr(MofList, Offset);
  1241. wcscpy(w, ResourceName);
  1242. if (WnodeSI->WnodeHeader.ProviderId == MOFEVENT_ACTION_REGISTRY_PATH)
  1243. {
  1244. MofEntry->Flags = 0;
  1245. } else {
  1246. MofEntry->Flags = WMIMOFENTRY_FLAG_USERMODE;
  1247. }
  1248. Status = WmipBuildMofAddRemoveEvent(WnodeSI,
  1249. MofList,
  1250. LanguageList,
  1251. LanguageCount,
  1252. TRUE,
  1253. Callback,
  1254. DeliveryContext,
  1255. IsAnsi);
  1256. //
  1257. // Free up memory used to hold the language list
  1258. //
  1259. for (i = 0; i < LanguageCount; i++)
  1260. {
  1261. WmipFree(LanguageList[i]);
  1262. }
  1263. WmipFree(LanguageList);
  1264. }
  1265. WmipFree(MofList);
  1266. } else {
  1267. Status = ERROR_NOT_ENOUGH_MEMORY;
  1268. }
  1269. if (Status != ERROR_SUCCESS)
  1270. {
  1271. //
  1272. // If the WNODE_ALL_DATA event wasn't fired then just fire the
  1273. // WNDOE_SINGLE_INSTANCE event so at least we get the language
  1274. // neutral mof
  1275. //
  1276. WnodeSI->WnodeHeader.Flags &= ~WNODE_FLAG_INTERNAL;
  1277. WmipMakeEventCallbacks((PWNODE_HEADER)WnodeSI,
  1278. Callback,
  1279. DeliveryContext,
  1280. IsAnsi);
  1281. }
  1282. }
  1283. void WmipProcessLanguageAddRemoveEvent(
  1284. IN PWNODE_SINGLE_INSTANCE WnodeSI,
  1285. IN NOTIFICATIONCALLBACK Callback,
  1286. IN ULONG_PTR DeliveryContext,
  1287. IN BOOLEAN IsAnsi
  1288. )
  1289. {
  1290. ULONG Status;
  1291. PWMIMOFLIST MofList;
  1292. PWCHAR Language;
  1293. //
  1294. // Get list of mof resources and build an event with the list of
  1295. // resources for the language that is coming or going
  1296. //
  1297. Status = WmipGetMofResourceList(&MofList);
  1298. if (Status == ERROR_SUCCESS)
  1299. {
  1300. Language = (PWCHAR)OffsetToPtr(WnodeSI,
  1301. WnodeSI->DataBlockOffset + sizeof(USHORT));
  1302. Status = WmipBuildMofAddRemoveEvent(WnodeSI,
  1303. MofList,
  1304. &Language,
  1305. 1,
  1306. FALSE,
  1307. Callback,
  1308. DeliveryContext,
  1309. IsAnsi);
  1310. }
  1311. }