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.

546 lines
13 KiB

  1. /*++
  2. Copyright (c) 1995-2000 Microsoft Corporation
  3. Module Name:
  4. pnpapi.c
  5. Abstract:
  6. This module contains the user-mode plug-and-play API stubs.
  7. Author:
  8. Paula Tomlinson (paulat) 9-18-1995
  9. Environment:
  10. User-mode only.
  11. Revision History:
  12. 18-Sept-1995 paulat
  13. Creation and initial implementation.
  14. --*/
  15. #ifndef UNICODE
  16. #define UNICODE
  17. #endif
  18. #ifndef _UNICODE
  19. #define _UNICODE
  20. #endif
  21. #define MAX_PROFILEID_LEN 5
  22. #define MAX_UUID_LEN 39
  23. //
  24. // includes
  25. //
  26. #include <nt.h>
  27. #include <ntrtl.h>
  28. #include <nturtl.h>
  29. #include <windows.h>
  30. #include <rpc.h>
  31. #include <rpcdce.h>
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34. #include <wtypes.h>
  35. //
  36. // private prototypes
  37. //
  38. PSTR
  39. UnicodeToMultiByte(
  40. IN PCWSTR UnicodeString,
  41. IN UINT Codepage
  42. );
  43. PWSTR
  44. MultiByteToUnicode(
  45. IN PCSTR String,
  46. IN UINT Codepage
  47. );
  48. RPC_STATUS
  49. GuidToString(
  50. UUID *Uuid,
  51. LPTSTR StringGuid
  52. );
  53. //
  54. // global data
  55. //
  56. WCHAR pszRegIDConfigDB[] = L"System\\CurrentControlSet\\Control\\IDConfigDB";
  57. WCHAR pszRegKnownDockingStates[] = L"Hardware Profiles";
  58. WCHAR pszRegCurrentConfig[] = L"CurrentConfig";
  59. WCHAR pszRegDefaultFriendlyName[] = L"Noname Hardware Profile";
  60. WCHAR pszRegHwProfileGuid[] = L"HwProfileGuid";
  61. WCHAR pszRegFriendlyName[] = L"FriendlyName";
  62. WCHAR pszRegDockState[] = L"DockState";
  63. WCHAR pszRegDockingState[] = L"DockingState";
  64. WCHAR pszCurrentDockInfo[] = L"CurrentDockInfo";
  65. BOOL
  66. GetCurrentHwProfileW (
  67. OUT LPHW_PROFILE_INFOW lpHwProfileInfo
  68. )
  69. /*++
  70. Routine Description:
  71. Arguments:
  72. lpHwProfileInfo Points to a HW_PROFILE_INFO structure that will receive
  73. the information for the current hardware profile.
  74. Return Value:
  75. If the function succeeds, the return value is TRUE. If the function
  76. fails, the return value is FALSE. To get extended error information,
  77. call GetLastError.
  78. --*/
  79. {
  80. BOOL Status = TRUE;
  81. WCHAR RegStr[MAX_PATH];
  82. HKEY hKey = NULL, hCfgKey = NULL;
  83. HKEY hCurrentDockInfoKey = NULL;
  84. ULONG ulCurrentConfig = 1, ulSize = 0;
  85. UUID NewGuid;
  86. try {
  87. //
  88. // validate parameter
  89. //
  90. if (lpHwProfileInfo == NULL) {
  91. SetLastError(ERROR_INVALID_PARAMETER);
  92. Status = FALSE;
  93. goto Clean0;
  94. }
  95. //
  96. // open the IDConfigDB key
  97. //
  98. if (RegOpenKeyEx(
  99. HKEY_LOCAL_MACHINE, pszRegIDConfigDB, 0,
  100. KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) {
  101. SetLastError(ERROR_REGISTRY_CORRUPT);
  102. Status = FALSE;
  103. goto Clean0;
  104. }
  105. //
  106. // retrieve the current config id
  107. //
  108. ulSize = sizeof(ULONG);
  109. if (RegQueryValueEx(hKey, pszRegCurrentConfig, NULL, NULL,
  110. (LPBYTE)&ulCurrentConfig, &ulSize) != ERROR_SUCCESS) {
  111. SetLastError(ERROR_REGISTRY_CORRUPT);
  112. Status = FALSE;
  113. goto Clean0;
  114. }
  115. //
  116. // open the profile key for the current configuration
  117. //
  118. _snwprintf(RegStr, MAX_PATH, L"%s\\%04u",
  119. pszRegKnownDockingStates,
  120. ulCurrentConfig);
  121. if (RegOpenKeyEx(hKey, RegStr, 0, KEY_QUERY_VALUE,
  122. &hCfgKey) != ERROR_SUCCESS) {
  123. SetLastError(ERROR_REGISTRY_CORRUPT);
  124. Status = FALSE;
  125. goto Clean0;
  126. }
  127. //
  128. // retrieve the dock state for the current profile
  129. //
  130. if (RegOpenKeyEx(hKey, pszCurrentDockInfo, 0, KEY_QUERY_VALUE,
  131. &hCurrentDockInfoKey) != ERROR_SUCCESS) {
  132. //
  133. // No CurrentDockInfo Key, something's wrong.
  134. //
  135. SetLastError(ERROR_REGISTRY_CORRUPT);
  136. Status = FALSE;
  137. goto Clean0;
  138. }
  139. //
  140. // Look in CurrentDockInfo for
  141. // a hardware determined DockingState value.
  142. //
  143. ulSize = sizeof(ULONG);
  144. if ((RegQueryValueEx(hCurrentDockInfoKey,
  145. pszRegDockingState,
  146. NULL,
  147. NULL,
  148. (LPBYTE)&lpHwProfileInfo->dwDockInfo,
  149. &ulSize) != ERROR_SUCCESS)
  150. || (!lpHwProfileInfo->dwDockInfo)
  151. || ((lpHwProfileInfo->dwDockInfo & DOCKINFO_UNDOCKED) &&
  152. (lpHwProfileInfo->dwDockInfo & DOCKINFO_DOCKED))) {
  153. //
  154. // If there's no such value, or the value was set to 0 (unspported),
  155. // or if the value is "unknown", resort to user supplied docking info.
  156. // Look under the IDConfigDB profile for a user set DockState value.
  157. //
  158. if ((RegQueryValueEx(hCfgKey, pszRegDockState, NULL, NULL,
  159. (LPBYTE)&lpHwProfileInfo->dwDockInfo,
  160. &ulSize) != ERROR_SUCCESS)
  161. || (!lpHwProfileInfo->dwDockInfo)) {
  162. //
  163. // If there's no such value, or the value was set to 0,
  164. // there is no user specified docking state to resort to;
  165. // return the "user-supplied unknown" docking state.
  166. //
  167. lpHwProfileInfo->dwDockInfo =
  168. DOCKINFO_USER_SUPPLIED | DOCKINFO_DOCKED | DOCKINFO_UNDOCKED;
  169. }
  170. }
  171. //
  172. // retrieve the profile guid. if we can't get one, set it to NULL
  173. //
  174. ulSize = HW_PROFILE_GUIDLEN * sizeof(WCHAR);
  175. if (RegQueryValueEx(hCfgKey, pszRegHwProfileGuid, NULL, NULL,
  176. (LPBYTE)&lpHwProfileInfo->szHwProfileGuid,
  177. &ulSize) != ERROR_SUCCESS) {
  178. lpHwProfileInfo->szHwProfileGuid[0] = '\0';
  179. }
  180. //
  181. // retrieve the friendly name. if we can't get one, set it to NULL
  182. //
  183. ulSize = MAX_PROFILE_LEN * sizeof(WCHAR);
  184. if (RegQueryValueEx(hCfgKey, pszRegFriendlyName, NULL, NULL,
  185. (LPBYTE)&lpHwProfileInfo->szHwProfileName,
  186. &ulSize) != ERROR_SUCCESS) {
  187. lpHwProfileInfo->szHwProfileName[0] = '\0';
  188. }
  189. Clean0:
  190. ;
  191. } except(EXCEPTION_EXECUTE_HANDLER) {
  192. SetLastError(ERROR_INVALID_PARAMETER);
  193. Status = FALSE;
  194. }
  195. if (hKey != NULL) RegCloseKey(hKey);
  196. if (hCfgKey != NULL) RegCloseKey(hCfgKey);
  197. if (hCurrentDockInfoKey != NULL) RegCloseKey(hCurrentDockInfoKey);
  198. return Status;
  199. } // GetCurrentHwProfileW
  200. BOOL
  201. GetCurrentHwProfileA (
  202. OUT LPHW_PROFILE_INFOA lpHwProfileInfo
  203. )
  204. /*++
  205. Routine Description:
  206. Arguments:
  207. lpHwProfileInfo Points to a HW_PROFILE_INFO structure that will receive
  208. the information for the current hardware profile.
  209. Return Value:
  210. If the function succeeds, the return value is TRUE. If the function
  211. fails, the return value is FALSE. To get extended error information,
  212. call GetLastError.
  213. --*/
  214. {
  215. BOOL Status = TRUE;
  216. HW_PROFILE_INFOW HwProfileInfoW;
  217. LPSTR pAnsiString;
  218. try {
  219. //
  220. // validate parameter
  221. //
  222. if (lpHwProfileInfo == NULL) {
  223. SetLastError(ERROR_INVALID_PARAMETER);
  224. Status = FALSE;
  225. goto Clean0;
  226. }
  227. //
  228. // call the Unicode version
  229. //
  230. if (!GetCurrentHwProfileW(&HwProfileInfoW)) {
  231. Status = FALSE;
  232. goto Clean0;
  233. }
  234. //
  235. // on successful return, convert unicode form of struct
  236. // to ANSI and copy struct members to callers struct
  237. //
  238. lpHwProfileInfo->dwDockInfo = HwProfileInfoW.dwDockInfo;
  239. pAnsiString = UnicodeToMultiByte(
  240. HwProfileInfoW.szHwProfileGuid, CP_ACP);
  241. if (!pAnsiString) {
  242. Status = FALSE;
  243. goto Clean0;
  244. }
  245. lstrcpyA(lpHwProfileInfo->szHwProfileGuid, pAnsiString);
  246. LocalFree(pAnsiString);
  247. pAnsiString = UnicodeToMultiByte(
  248. HwProfileInfoW.szHwProfileName, CP_ACP);
  249. if (!pAnsiString) {
  250. Status = FALSE;
  251. goto Clean0;
  252. }
  253. lstrcpyA(lpHwProfileInfo->szHwProfileName, pAnsiString);
  254. LocalFree(pAnsiString);
  255. Clean0:
  256. ;
  257. } except(EXCEPTION_EXECUTE_HANDLER) {
  258. SetLastError(ERROR_INTERNAL_ERROR);
  259. Status = FALSE;
  260. }
  261. return Status;
  262. } // GetCurrentHwProfileA
  263. PSTR
  264. UnicodeToMultiByte(
  265. IN PCWSTR UnicodeString,
  266. IN UINT Codepage
  267. )
  268. /*++
  269. Routine Description:
  270. Convert a string from unicode to ansi.
  271. Arguments:
  272. UnicodeString - supplies string to be converted.
  273. Codepage - supplies codepage to be used for the conversion.
  274. Return Value:
  275. NULL if out of memory or invalid codepage.
  276. Caller can free buffer with MyFree().
  277. --*/
  278. {
  279. UINT WideCharCount;
  280. PSTR String;
  281. UINT StringBufferSize;
  282. UINT BytesInString;
  283. PSTR p;
  284. WideCharCount = lstrlenW(UnicodeString) + 1;
  285. //
  286. // Allocate maximally sized buffer.
  287. // If every unicode character is a double-byte
  288. // character, then the buffer needs to be the same size
  289. // as the unicode string. Otherwise it might be smaller,
  290. // as some unicode characters will translate to
  291. // single-byte characters.
  292. //
  293. StringBufferSize = WideCharCount * sizeof(WCHAR);
  294. String = (PSTR)LocalAlloc(LPTR, StringBufferSize);
  295. if(String == NULL) {
  296. return(NULL);
  297. }
  298. //
  299. // Perform the conversion.
  300. //
  301. BytesInString = WideCharToMultiByte(
  302. Codepage,
  303. 0, // default composite char behavior
  304. UnicodeString,
  305. WideCharCount,
  306. String,
  307. StringBufferSize,
  308. NULL,
  309. NULL
  310. );
  311. if(BytesInString == 0) {
  312. LocalFree(String);
  313. return(NULL);
  314. }
  315. //
  316. // Resize the string's buffer to its correct size.
  317. // If the realloc fails for some reason the original
  318. // buffer is not freed.
  319. //
  320. if(p = LocalReAlloc(String,BytesInString, LMEM_ZEROINIT | LMEM_MOVEABLE)) {
  321. String = p;
  322. }
  323. return(String);
  324. } // UnicodeToMultiByte
  325. PWSTR
  326. MultiByteToUnicode(
  327. IN PCSTR String,
  328. IN UINT Codepage
  329. )
  330. /*++
  331. Routine Description:
  332. Convert a string to unicode.
  333. Arguments:
  334. String - supplies string to be converted.
  335. Codepage - supplies codepage to be used for the conversion.
  336. Return Value:
  337. NULL if string could not be converted (out of memory or invalid cp)
  338. Caller can free buffer with MyFree().
  339. --*/
  340. {
  341. UINT BytesIn8BitString;
  342. UINT CharsInUnicodeString;
  343. PWSTR UnicodeString;
  344. PWSTR p;
  345. BytesIn8BitString = lstrlenA(String) + 1;
  346. //
  347. // Allocate maximally sized buffer.
  348. // If every character is a single-byte character,
  349. // then the buffer needs to be twice the size
  350. // as the 8bit string. Otherwise it might be smaller,
  351. // as some characters are 2 bytes in their unicode and
  352. // 8bit representations.
  353. //
  354. UnicodeString = (PWSTR)LocalAlloc(LPTR, BytesIn8BitString * sizeof(WCHAR));
  355. if(UnicodeString == NULL) {
  356. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  357. return(NULL);
  358. }
  359. //
  360. // Perform the conversion.
  361. //
  362. CharsInUnicodeString = MultiByteToWideChar(
  363. Codepage,
  364. MB_PRECOMPOSED,
  365. String,
  366. BytesIn8BitString,
  367. UnicodeString,
  368. BytesIn8BitString
  369. );
  370. if(CharsInUnicodeString == 0) {
  371. LocalFree(UnicodeString);
  372. return(NULL);
  373. }
  374. //
  375. // Resize the unicode string's buffer to its correct size.
  376. // If the realloc fails for some reason the original
  377. // buffer is not freed.
  378. //
  379. if(p = (PWSTR)LocalReAlloc(UnicodeString,CharsInUnicodeString*sizeof(WCHAR),
  380. LMEM_ZEROINIT | LMEM_MOVEABLE)) {
  381. UnicodeString = p;
  382. }
  383. return(UnicodeString);
  384. } // MultiByteToUnicode
  385. RPC_STATUS
  386. GuidToString(
  387. UUID *Uuid,
  388. LPTSTR StringGuid
  389. )
  390. {
  391. RPC_STATUS Status;
  392. LPTSTR pTempStringGuid;
  393. UNICODE_STRING UnicodeStringGuid;
  394. Status = UuidToString(Uuid, &pTempStringGuid);
  395. if (Status == RPC_S_OK) {
  396. //
  397. // the form we want is all uppercase and with curly brackets around,
  398. // like what OLE does
  399. //
  400. lstrcpy(StringGuid, TEXT("{"));
  401. lstrcat(StringGuid, pTempStringGuid);
  402. lstrcat(StringGuid, TEXT("}"));
  403. RtlInitUnicodeString(&UnicodeStringGuid, StringGuid);
  404. RtlUpcaseUnicodeString(&UnicodeStringGuid, &UnicodeStringGuid, FALSE);
  405. RpcStringFree(&pTempStringGuid);
  406. }
  407. return Status;
  408. } // GuidToString