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.

542 lines
13 KiB

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