Windows NT 4.0 source code leak
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.

550 lines
12 KiB

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