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.

935 lines
25 KiB

  1. /****************************************************************************\
  2. *
  3. * Module Name : regapi.c
  4. *
  5. * Multimedia support library
  6. *
  7. * This module contains the code for accessing the registry
  8. *
  9. * Copyright (c) 1993-1998 Microsoft Corporation
  10. *
  11. \****************************************************************************/
  12. #define UNICODE
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <regapi.h>
  17. #include "winmmi.h"
  18. HANDLE Drivers32Handle;
  19. static WCHAR gszMsacmDriver[] = L"msacm.";
  20. /*
  21. ** Free everything cached
  22. */
  23. VOID mmRegFree(VOID)
  24. {
  25. if (Drivers32Handle != NULL) {
  26. NtClose(Drivers32Handle);
  27. Drivers32Handle = NULL;
  28. }
  29. }
  30. /*
  31. ** Open a subkey
  32. */
  33. HANDLE mmRegOpenSubkey(HANDLE BaseKeyHandle, LPCWSTR lpszSubkeyName)
  34. {
  35. UNICODE_STRING unicodeSectionName;
  36. HANDLE KeyHandle;
  37. OBJECT_ATTRIBUTES oa;
  38. RtlInitUnicodeString(&unicodeSectionName, lpszSubkeyName);
  39. InitializeObjectAttributes(&oa,
  40. &unicodeSectionName,
  41. OBJ_CASE_INSENSITIVE,
  42. BaseKeyHandle,
  43. (PSECURITY_DESCRIPTOR)NULL);
  44. /*
  45. ** Open the sub section
  46. */
  47. if (!NT_SUCCESS(NtOpenKey(&KeyHandle, GENERIC_READ, &oa))) {
  48. return NULL;
  49. } else {
  50. return KeyHandle;
  51. }
  52. }
  53. /*
  54. ** Open a subkey
  55. */
  56. HANDLE mmRegOpenSubkeyForWrite(HANDLE BaseKeyHandle, LPCWSTR lpszSubkeyName)
  57. {
  58. UNICODE_STRING unicodeSectionName;
  59. HANDLE KeyHandle;
  60. OBJECT_ATTRIBUTES oa;
  61. RtlInitUnicodeString(&unicodeSectionName, lpszSubkeyName);
  62. InitializeObjectAttributes(&oa,
  63. &unicodeSectionName,
  64. OBJ_CASE_INSENSITIVE,
  65. BaseKeyHandle,
  66. (PSECURITY_DESCRIPTOR)NULL);
  67. /*
  68. ** Open the sub section
  69. */
  70. if (!NT_SUCCESS(NtOpenKey(&KeyHandle, MAXIMUM_ALLOWED, &oa))) {
  71. return NULL;
  72. } else {
  73. return KeyHandle;
  74. }
  75. }
  76. /*
  77. ** Read (small) registry data entries
  78. */
  79. BOOL mmRegQueryValue(HANDLE BaseKeyHandle,
  80. LPCWSTR lpszSubkeyName,
  81. LPCWSTR lpszValueName,
  82. ULONG dwLen,
  83. LPWSTR lpszValue)
  84. {
  85. BOOL ReturnCode;
  86. HANDLE KeyHandle;
  87. UNICODE_STRING unicodeSectionName;
  88. UNICODE_STRING unicodeValueName;
  89. ULONG ResultLength;
  90. struct {
  91. KEY_VALUE_PARTIAL_INFORMATION KeyInfo;
  92. UCHAR Data[MAX_PATH * sizeof(WCHAR)];
  93. } OurKeyValueInformation;
  94. if (lpszSubkeyName) {
  95. KeyHandle = mmRegOpenSubkey(BaseKeyHandle, lpszSubkeyName);
  96. } else {
  97. KeyHandle = NULL;
  98. }
  99. /*
  100. ** Read the data
  101. */
  102. if (lpszValueName == NULL) {
  103. RtlInitUnicodeString(&unicodeValueName, TEXT(""));
  104. } else {
  105. RtlInitUnicodeString(&unicodeValueName, lpszValueName);
  106. }
  107. ReturnCode = NT_SUCCESS(NtQueryValueKey(KeyHandle == NULL ?
  108. BaseKeyHandle : KeyHandle,
  109. &unicodeValueName,
  110. KeyValuePartialInformation,
  111. (PVOID)&OurKeyValueInformation,
  112. sizeof(OurKeyValueInformation),
  113. &ResultLength));
  114. if (ReturnCode) {
  115. /*
  116. ** Check we got the right type of data and not too much
  117. */
  118. if (OurKeyValueInformation.KeyInfo.DataLength > dwLen * sizeof(WCHAR) ||
  119. (OurKeyValueInformation.KeyInfo.Type != REG_SZ &&
  120. OurKeyValueInformation.KeyInfo.Type != REG_EXPAND_SZ)) {
  121. ReturnCode = FALSE;
  122. } else {
  123. /*
  124. ** Copy back the data
  125. */
  126. if (OurKeyValueInformation.KeyInfo.Type == REG_EXPAND_SZ) {
  127. lpszValue[0] = TEXT('\0');
  128. ExpandEnvironmentStringsW
  129. ((LPCWSTR)OurKeyValueInformation.KeyInfo.Data,
  130. (LPWSTR)lpszValue,
  131. dwLen);
  132. } else {
  133. CopyMemory((PVOID)lpszValue,
  134. (PVOID)OurKeyValueInformation.KeyInfo.Data,
  135. dwLen * sizeof(WCHAR));
  136. lpszValue[ min(OurKeyValueInformation.KeyInfo.DataLength,
  137. dwLen-1) ] = TEXT('\0');
  138. }
  139. }
  140. }
  141. if (KeyHandle) {
  142. NtClose(KeyHandle);
  143. }
  144. return ReturnCode;
  145. }
  146. /*
  147. ** Read a mapped 'user' value in a known section
  148. */
  149. BOOL mmRegQueryUserValue(LPCWSTR lpszSectionName,
  150. LPCWSTR lpszValueName,
  151. ULONG dwLen,
  152. LPWSTR lpszValue)
  153. {
  154. HANDLE UserHandle;
  155. BOOL ReturnCode;
  156. /*
  157. ** Open the user's key. It's important to do this EACH time because
  158. ** on the server it's different for different threads.
  159. */
  160. if (!NT_SUCCESS(RtlOpenCurrentUser(GENERIC_READ, &UserHandle))) {
  161. return FALSE;
  162. }
  163. ReturnCode = mmRegQueryValue(UserHandle,
  164. lpszSectionName,
  165. lpszValueName,
  166. dwLen,
  167. lpszValue);
  168. NtClose(UserHandle);
  169. return ReturnCode;
  170. }
  171. /*
  172. ** Set a mapped 'user' value in a known section
  173. */
  174. BOOL mmRegSetUserValue(LPCWSTR lpszSectionName,
  175. LPCWSTR lpszValueName,
  176. LPCWSTR lpszValue)
  177. {
  178. HANDLE UserHandle;
  179. BOOL ReturnCode = FALSE;
  180. /*
  181. ** Open the user's key. It's important to do this EACH time because
  182. ** on the server it's different for different threads.
  183. */
  184. if (NT_SUCCESS(RtlOpenCurrentUser(MAXIMUM_ALLOWED, &UserHandle)))
  185. {
  186. HANDLE KeyHandle;
  187. KeyHandle = mmRegOpenSubkeyForWrite (UserHandle, lpszSectionName);
  188. if (KeyHandle != NULL)
  189. {
  190. UNICODE_STRING ValueName;
  191. if (lpszValueName == NULL) {
  192. RtlInitUnicodeString (&ValueName, TEXT(""));
  193. } else {
  194. RtlInitUnicodeString (&ValueName, lpszValueName);
  195. }
  196. ReturnCode = NT_SUCCESS( NtSetValueKey (KeyHandle,
  197. &ValueName,
  198. 0,
  199. REG_SZ,
  200. (PVOID)lpszValue,
  201. (lstrlenW(lpszValue)+1)* sizeof(lpszValue[0])
  202. ) );
  203. NtClose(KeyHandle);
  204. }
  205. NtClose(UserHandle);
  206. }
  207. return ReturnCode;
  208. }
  209. BOOL mmRegCreateUserKey (LPCWSTR lpszPath, LPCWSTR lpszNewKey)
  210. {
  211. HANDLE UserHandle;
  212. BOOL ReturnValue = FALSE;
  213. /*
  214. ** Open the user's key. It's important to do this EACH time because
  215. ** on the server it's different for different threads.
  216. */
  217. if (NT_SUCCESS(RtlOpenCurrentUser(MAXIMUM_ALLOWED, &UserHandle)))
  218. {
  219. HANDLE PathHandle;
  220. HANDLE KeyHandle;
  221. UNICODE_STRING unicodeSectionName;
  222. OBJECT_ATTRIBUTES oa;
  223. if (lpszPath == NULL)
  224. {
  225. PathHandle = NULL;
  226. }
  227. else
  228. {
  229. PathHandle = mmRegOpenSubkeyForWrite (UserHandle, lpszPath);
  230. if (PathHandle == NULL)
  231. {
  232. NtClose(UserHandle);
  233. return FALSE;
  234. }
  235. }
  236. RtlInitUnicodeString(&unicodeSectionName, lpszNewKey);
  237. InitializeObjectAttributes(&oa,
  238. &unicodeSectionName,
  239. OBJ_CASE_INSENSITIVE,
  240. (PathHandle == NULL)
  241. ? UserHandle : PathHandle,
  242. (PSECURITY_DESCRIPTOR)NULL);
  243. /*
  244. ** Create the sub section
  245. */
  246. if (NT_SUCCESS( NtCreateKey(&KeyHandle,
  247. KEY_READ | KEY_WRITE,
  248. &oa,
  249. 0,
  250. NULL,
  251. 0,
  252. NULL
  253. ) ))
  254. {
  255. if (KeyHandle)
  256. {
  257. ReturnValue = TRUE;
  258. NtClose (KeyHandle);
  259. }
  260. }
  261. if (PathHandle != NULL)
  262. {
  263. NtClose(PathHandle);
  264. }
  265. NtClose(UserHandle);
  266. }
  267. return ReturnValue;
  268. }
  269. /*
  270. ** Test whether a mapped 'user' key exists
  271. */
  272. BOOL mmRegQueryUserKey (LPCWSTR lpszKeyName)
  273. {
  274. HANDLE UserHandle;
  275. BOOL ReturnValue = FALSE;
  276. if (lpszKeyName == NULL)
  277. {
  278. return FALSE;
  279. }
  280. if (NT_SUCCESS(RtlOpenCurrentUser(MAXIMUM_ALLOWED, &UserHandle)))
  281. {
  282. HANDLE KeyHandle;
  283. KeyHandle = mmRegOpenSubkeyForWrite (UserHandle, lpszKeyName);
  284. if (KeyHandle != NULL)
  285. {
  286. ReturnValue = TRUE;
  287. NtClose(KeyHandle);
  288. }
  289. NtClose(UserHandle);
  290. }
  291. return ReturnValue;
  292. }
  293. /*
  294. ** Delete a mapped 'user' key. Careful--this function deletes recursively!
  295. */
  296. #define nMaxLevelsToRecurseInDELETEKEY 3 // don't runaway or stack fault
  297. BOOL mmRegDeleteUserKeyRecurse (HANDLE UserHandle, LPCWSTR lpszName, int level)
  298. {
  299. HANDLE KeyHandle;
  300. if (lpszName == NULL)
  301. {
  302. return FALSE;
  303. }
  304. if (level > nMaxLevelsToRecurseInDELETEKEY)
  305. {
  306. return FALSE;
  307. }
  308. if ((KeyHandle = mmRegOpenSubkeyForWrite (UserHandle, lpszName)) != NULL)
  309. {
  310. struct {
  311. KEY_BASIC_INFORMATION kbi;
  312. WCHAR NameBuffer [MAX_PATH];
  313. } kbi;
  314. /*
  315. ** Before NtDeleteKey() will work on this key, we have to ensure
  316. ** there are no subkeys.
  317. */
  318. while (TRUE)
  319. {
  320. ULONG cbReturned = 0L;
  321. WCHAR szSubKeyName[ MAX_PATH ];
  322. ZeroMemory (&kbi, sizeof(kbi));
  323. if (!NT_SUCCESS(NtEnumerateKey(KeyHandle,
  324. 0,
  325. KeyBasicInformation,
  326. (PVOID)&kbi,
  327. sizeof(kbi),
  328. &cbReturned)))
  329. {
  330. break;
  331. }
  332. wsprintf (szSubKeyName, L"%ls\\%ls", lpszName, kbi.kbi.Name);
  333. if (!mmRegDeleteUserKeyRecurse (UserHandle, szSubKeyName, 1+level))
  334. {
  335. NtClose (KeyHandle);
  336. return FALSE;
  337. }
  338. }
  339. /*
  340. ** Once there are no subkeys, we should be able to delete this key.
  341. */
  342. if (NT_SUCCESS(NtDeleteKey(KeyHandle)))
  343. {
  344. NtClose(KeyHandle);
  345. return TRUE;
  346. }
  347. NtClose(KeyHandle);
  348. }
  349. return FALSE;
  350. }
  351. BOOL mmRegDeleteUserKey (LPCWSTR lpszKeyName)
  352. {
  353. HANDLE UserHandle;
  354. BOOL ReturnValue = FALSE;
  355. if (lpszKeyName == NULL)
  356. {
  357. return FALSE;
  358. }
  359. if (NT_SUCCESS(RtlOpenCurrentUser(MAXIMUM_ALLOWED, &UserHandle)))
  360. {
  361. ReturnValue = mmRegDeleteUserKeyRecurse (UserHandle, lpszKeyName, 1);
  362. NtClose(UserHandle);
  363. }
  364. return ReturnValue;
  365. }
  366. /*
  367. ** Read a mapped 'HKLM' value in a known section
  368. */
  369. BOOL mmRegQueryMachineValue(LPCWSTR lpszSectionName,
  370. LPCWSTR lpszValueName,
  371. ULONG dwLen,
  372. LPWSTR lpszValue)
  373. {
  374. WCHAR FullKeyName[MAX_PATH];
  375. HANDLE HostHandle;
  376. BOOL ReturnCode = FALSE;
  377. lstrcpyW (FullKeyName, L"\\Registry\\Machine\\");
  378. wcsncat (FullKeyName, lpszSectionName, (MAX_PATH - wcslen(FullKeyName) - 1));
  379. if ((HostHandle = mmRegOpenSubkey (NULL, FullKeyName)) != NULL)
  380. {
  381. ReturnCode = mmRegQueryValue (HostHandle,
  382. lpszSectionName,
  383. lpszValueName,
  384. dwLen,
  385. lpszValue);
  386. NtClose (HostHandle);
  387. }
  388. return ReturnCode;
  389. }
  390. /*
  391. ** Write a mapped 'HKLM' value in a known section
  392. */
  393. BOOL mmRegSetMachineValue(LPCWSTR lpszSectionName,
  394. LPCWSTR lpszValueName,
  395. LPCWSTR lpszValue)
  396. {
  397. WCHAR FullKeyName[MAX_PATH];
  398. HANDLE HostHandle;
  399. BOOL ReturnCode = FALSE;
  400. lstrcpyW (FullKeyName, L"\\Registry\\Machine\\");
  401. wcsncat (FullKeyName, lpszSectionName, (MAX_PATH - wcslen(FullKeyName) - 1));
  402. if ((HostHandle = mmRegOpenSubkeyForWrite (NULL, FullKeyName)) != NULL)
  403. {
  404. UNICODE_STRING ValueName;
  405. if (lpszValueName == NULL) {
  406. RtlInitUnicodeString (&ValueName, TEXT(""));
  407. } else {
  408. RtlInitUnicodeString (&ValueName, lpszValueName);
  409. }
  410. ReturnCode = NT_SUCCESS( NtSetValueKey (HostHandle,
  411. &ValueName,
  412. 0,
  413. REG_SZ,
  414. (PVOID)lpszValue,
  415. (lstrlenW(lpszValue)+1)* sizeof(lpszValue[0])
  416. ) );
  417. NtClose(HostHandle);
  418. }
  419. return ReturnCode;
  420. }
  421. BOOL mmRegCreateMachineKey (LPCWSTR lpszPath, LPCWSTR lpszNewKey)
  422. {
  423. WCHAR FullKeyName[MAX_PATH];
  424. HANDLE HostHandle;
  425. BOOL ReturnValue = FALSE;
  426. lstrcpyW (FullKeyName, L"\\Registry\\Machine\\");
  427. wcsncat (FullKeyName, lpszPath, (MAX_PATH - wcslen(FullKeyName) - 1));
  428. if ((HostHandle = mmRegOpenSubkeyForWrite (NULL, FullKeyName)) != NULL)
  429. {
  430. HANDLE KeyHandle;
  431. UNICODE_STRING unicodeSectionName;
  432. OBJECT_ATTRIBUTES oa;
  433. RtlInitUnicodeString(&unicodeSectionName, lpszNewKey);
  434. InitializeObjectAttributes(&oa,
  435. &unicodeSectionName,
  436. OBJ_CASE_INSENSITIVE,
  437. HostHandle,
  438. (PSECURITY_DESCRIPTOR)NULL);
  439. /*
  440. ** Create the sub section
  441. */
  442. if (NT_SUCCESS( NtCreateKey(&KeyHandle,
  443. KEY_READ | KEY_WRITE,
  444. &oa,
  445. 0,
  446. NULL,
  447. 0,
  448. NULL
  449. ) ))
  450. {
  451. if (KeyHandle)
  452. {
  453. ReturnValue = TRUE;
  454. NtClose (KeyHandle);
  455. }
  456. }
  457. NtClose(HostHandle);
  458. }
  459. return ReturnValue;
  460. }
  461. /*
  462. ** Read stuff from system.ini
  463. */
  464. BOOL mmRegQuerySystemIni(LPCWSTR lpszSectionName,
  465. LPCWSTR lpszValueName,
  466. ULONG dwLen,
  467. LPWSTR lpszValue)
  468. {
  469. WCHAR KeyPathBuffer[MAX_PATH];
  470. WCHAR ExKeyPathBuffer[MAX_PATH];
  471. /*
  472. ** Create the full path
  473. */
  474. lstrcpy(KeyPathBuffer,
  475. (LPCTSTR) L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\");
  476. wcsncat(KeyPathBuffer, lpszSectionName, (MAX_PATH - wcslen(KeyPathBuffer) - 1));
  477. if (lstrcmpiW(lpszSectionName, wszDrivers) == 0) {
  478. //
  479. // for remote session, look ..\terminal Server\RDP (or other protocols) for drivers32
  480. // name
  481. //
  482. //
  483. if (WinmmRunningInSession) {
  484. lstrcat(KeyPathBuffer,L"\\");
  485. lstrcat(KeyPathBuffer, REG_TSERVER);
  486. lstrcat(KeyPathBuffer,L"\\");
  487. lstrcat(KeyPathBuffer, SessionProtocolName);
  488. }
  489. if (Drivers32Handle == NULL) {
  490. Drivers32Handle = mmRegOpenSubkey(NULL, KeyPathBuffer);
  491. }
  492. if (Drivers32Handle != NULL) {
  493. BOOL rc;
  494. rc = mmRegQueryValue(Drivers32Handle,
  495. NULL,
  496. lpszValueName,
  497. dwLen,
  498. lpszValue);
  499. //
  500. // If we can't find the codec in the TermSrv protocol path
  501. // we will look under Driver32 next
  502. //
  503. if (rc == FALSE && WinmmRunningInSession &&
  504. _wcsnicmp(lpszValueName, gszMsacmDriver, lstrlen(gszMsacmDriver)) == 0) {
  505. HANDLE hKey;
  506. /*
  507. ** Create the full path
  508. */
  509. lstrcpy(KeyPathBuffer,
  510. (LPCTSTR) L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\");
  511. lstrcat(KeyPathBuffer, lpszSectionName);
  512. hKey = mmRegOpenSubkey(NULL, KeyPathBuffer);
  513. if (hKey != NULL) {
  514. rc = mmRegQueryValue(hKey,
  515. NULL,
  516. lpszValueName,
  517. dwLen,
  518. lpszValue);
  519. RegCloseKey(hKey);
  520. return rc;
  521. }
  522. else {
  523. return FALSE;
  524. }
  525. }
  526. else {
  527. return rc;
  528. }
  529. } else {
  530. return FALSE;
  531. }
  532. }
  533. if (WinmmRunningInSession) {
  534. if (lstrcmpiW(lpszSectionName, MCI_SECTION) == 0) {
  535. memset(ExKeyPathBuffer, 0 , sizeof(ExKeyPathBuffer));
  536. lstrcpy(ExKeyPathBuffer, KeyPathBuffer);
  537. lstrcat(ExKeyPathBuffer,L"\\");
  538. lstrcat(ExKeyPathBuffer, REG_TSERVER);
  539. lstrcat(ExKeyPathBuffer,L"\\");
  540. lstrcat(ExKeyPathBuffer, SessionProtocolName);
  541. /* look through terminal server section for drivers information first */
  542. if (mmRegQueryValue(NULL, ExKeyPathBuffer, lpszValueName, dwLen, lpszValue))
  543. return TRUE;
  544. else {
  545. /* pick the system default drivers information */
  546. return mmRegQueryValue(NULL, KeyPathBuffer, lpszValueName, dwLen, lpszValue);
  547. }
  548. }
  549. }
  550. return mmRegQueryValue(NULL, KeyPathBuffer, lpszValueName, dwLen, lpszValue);
  551. }
  552. /*
  553. ** Translate name through sounds section
  554. */
  555. BOOL mmRegQuerySound(LPCWSTR lpszSoundName,
  556. ULONG dwLen,
  557. LPWSTR lpszValue)
  558. {
  559. WCHAR KeyPathBuffer[MAX_PATH];
  560. lstrcpy(KeyPathBuffer, (LPCWSTR)L"Control Panel\\");
  561. lstrcat(KeyPathBuffer, szSoundSection);
  562. return mmRegQueryUserValue(KeyPathBuffer,
  563. lpszSoundName,
  564. dwLen,
  565. lpszValue);
  566. }
  567. BOOL IsAliasName(LPCWSTR lpSection, LPCWSTR lpKeyName)
  568. {
  569. if ((!wcsncmp(lpKeyName, L"wave", 4)) ||
  570. (!wcsncmp(lpKeyName, L"midi", 4)) ||
  571. (!wcsncmp(lpKeyName, L"aux", 3 )) ||
  572. (!wcsncmp(lpKeyName, L"mixer",5)) ||
  573. (!wcsncmp(lpKeyName, L"msacm",5)) ||
  574. (!wcsncmp(lpKeyName, L"vidc",4)) ||
  575. (!wcsncmp(lpKeyName, L"midimapper", 10)) ||
  576. (!wcsncmp(lpKeyName, L"wavemapper", 10)) ||
  577. (!wcsncmp(lpKeyName, L"auxmapper", 9 )) ||
  578. (!wcsncmp(lpKeyName, L"mixermapper", 11)))
  579. {
  580. return TRUE;
  581. }
  582. else
  583. {
  584. if (lstrcmpiW( lpSection, (LPCWSTR)MCI_HANDLERS) == 0L)
  585. {
  586. UINT n = lstrlen(lpKeyName);
  587. for (; n > 0; n--)
  588. {
  589. // Found a '.' which implies and extension, which implies a
  590. // file.
  591. if ('.' == lpKeyName[n-1])
  592. {
  593. return FALSE;
  594. }
  595. }
  596. // Searched the string for '.'.
  597. // None so it is an alias (that is -- not filename)
  598. return TRUE;
  599. }
  600. if (lstrcmpiW( lpSection, (LPCWSTR)wszDrivers) == 0L)
  601. {
  602. WCHAR szFileName[MAX_PATH];
  603. // It could be something REALLY off the wall, like "ReelDrv"
  604. return (mmRegQuerySystemIni(lpSection, lpKeyName, MAX_PATH, szFileName));
  605. }
  606. return FALSE;
  607. }
  608. }
  609. /*****************************Private*Routine******************************\
  610. * MyGetPrivateProfileString
  611. *
  612. * Attempt to bypass stevewo's private profile stuff.
  613. *
  614. * History:
  615. * dd-mm-93 - StephenE - Created
  616. *
  617. \**************************************************************************/
  618. DWORD
  619. winmmGetPrivateProfileString(
  620. LPCWSTR lpSection,
  621. LPCWSTR lpKeyName,
  622. LPCWSTR lpDefault,
  623. LPWSTR lpReturnedString,
  624. DWORD nSize,
  625. LPCWSTR lpFileName
  626. )
  627. {
  628. WCHAR szFileName[MAX_PATH];
  629. /*
  630. ** for now just look for to the [Drivers32] section of system.ini
  631. */
  632. if ( (lstrcmpiW( lpFileName, wszSystemIni ) == 0L)
  633. && ( ( lstrcmpiW( lpSection, wszDrivers ) == 0L ) ||
  634. ( lstrcmpiW( lpSection, (LPCWSTR)MCI_HANDLERS) == 0L ) ) ) {
  635. if (IsAliasName(lpSection, lpKeyName))
  636. {
  637. if (mmRegQuerySystemIni(lpSection, lpKeyName, nSize, lpReturnedString))
  638. {
  639. return lstrlen(lpReturnedString);
  640. }
  641. else
  642. {
  643. return 0;
  644. }
  645. }
  646. else
  647. {
  648. UINT ii;
  649. HANDLE hFile;
  650. lstrcpyW(szFileName, lpKeyName);
  651. for (ii = 0; 0 != szFileName[ii]; ii++)
  652. {
  653. if(' ' == szFileName[ii])
  654. {
  655. // Truncate parameters...
  656. szFileName[ii] = 0;
  657. break;
  658. }
  659. }
  660. hFile = CreateFile(
  661. szFileName,
  662. 0,
  663. FILE_SHARE_READ,
  664. NULL,
  665. OPEN_EXISTING,
  666. FILE_ATTRIBUTE_NORMAL,
  667. NULL);
  668. if(INVALID_HANDLE_VALUE != hFile)
  669. {
  670. CloseHandle(hFile);
  671. wcsncpy(lpReturnedString, lpKeyName, nSize);
  672. return (lstrlenW(lpKeyName));
  673. }
  674. else
  675. {
  676. // Okay was it a full file path?
  677. for(ii = 0; 0 != szFileName[ii]; ii++)
  678. {
  679. if ('\\' == szFileName[ii])
  680. {
  681. // Probably...
  682. break;
  683. }
  684. }
  685. if ('\\' != szFileName[ii])
  686. {
  687. WCHAR szStub[MAX_PATH];
  688. LPWSTR pszFilePart;
  689. lstrcpyW(szStub, lpKeyName);
  690. for(ii = 0; 0 != szStub[ii]; ii++)
  691. {
  692. if(' ' == szStub[ii])
  693. {
  694. // Truncate parameters...
  695. szStub[ii] = 0;
  696. break;
  697. }
  698. }
  699. if (!SearchPathW(NULL,
  700. szStub,
  701. NULL,
  702. MAX_PATH,
  703. szFileName,
  704. &pszFilePart))
  705. {
  706. return (0);
  707. }
  708. hFile = CreateFile(
  709. szFileName,
  710. 0,
  711. FILE_SHARE_READ,
  712. NULL,
  713. OPEN_EXISTING,
  714. FILE_ATTRIBUTE_NORMAL,
  715. NULL);
  716. if(INVALID_HANDLE_VALUE != hFile)
  717. {
  718. CloseHandle(hFile);
  719. wcsncpy(lpReturnedString, lpKeyName, nSize);
  720. return (lstrlenW(lpKeyName));
  721. }
  722. }
  723. }
  724. if (lpDefault != NULL) {
  725. wcsncpy(lpReturnedString, lpDefault, nSize);
  726. }
  727. return 0;
  728. }
  729. }
  730. else {
  731. return GetPrivateProfileStringW( lpSection, lpKeyName, lpDefault,
  732. lpReturnedString, nSize, lpFileName );
  733. }
  734. }
  735. DWORD
  736. winmmGetProfileString(
  737. LPCWSTR lpAppName,
  738. LPCWSTR lpKeyName,
  739. LPCWSTR lpDefault,
  740. LPWSTR lpReturnedString,
  741. DWORD nSize
  742. )
  743. {
  744. /*
  745. ** See if it's one we know about
  746. */
  747. if (lstrcmpiW(lpAppName, szSoundSection) == 0) {
  748. if (mmRegQuerySound(lpKeyName, nSize, lpReturnedString)) {
  749. return lstrlen(lpReturnedString);
  750. } else {
  751. if (lpDefault != NULL) {
  752. wcsncpy(lpReturnedString, lpDefault, nSize);
  753. }
  754. return FALSE;
  755. }
  756. } else {
  757. return GetProfileString(lpAppName,
  758. lpKeyName,
  759. lpDefault,
  760. lpReturnedString,
  761. nSize);
  762. }
  763. }