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.

1387 lines
38 KiB

  1. /*************************************************************************
  2. *
  3. * query.c
  4. *
  5. * Query Register APIs
  6. *
  7. * Copyright (c) 1998 Microsoft Corporation
  8. *
  9. *
  10. *************************************************************************/
  11. /*
  12. * Includes
  13. */
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <windows.h>
  21. #include <ntddkbd.h>
  22. #include <ntddmou.h>
  23. #include <winstaw.h>
  24. #include <regapi.h>
  25. /*
  26. * Procedures defined
  27. */
  28. VOID QueryWinStaCreate( HKEY, PWINSTATIONCREATE );
  29. VOID QueryUserConfig( HKEY, PUSERCONFIG );
  30. VOID QueryConfig( HKEY, PWINSTATIONCONFIG );
  31. VOID QueryNetwork( HKEY, PNETWORKCONFIG );
  32. VOID QueryNasi( HKEY, PNASICONFIG );
  33. VOID QueryAsync( HKEY, PASYNCCONFIG );
  34. VOID QueryOemTd( HKEY, POEMTDCONFIG );
  35. VOID QueryFlow( HKEY, PFLOWCONTROLCONFIG );
  36. VOID QueryConnect( HKEY, PCONNECTCONFIG );
  37. VOID QueryCd( HKEY, PCDCONFIG );
  38. VOID QueryWd( HKEY, PWDCONFIG );
  39. VOID QueryPdConfig( HKEY, PPDCONFIG, PULONG );
  40. VOID QueryPdConfig2( HKEY, PPDCONFIG2, ULONG );
  41. VOID QueryPdConfig3( HKEY, PPDCONFIG3, ULONG );
  42. VOID QueryPdParams( HKEY, SDCLASS, PPDPARAMS );
  43. BOOLEAN WINAPI RegBuildNumberQuery( PULONG );
  44. BOOLEAN RegQueryOEMId( PBYTE, ULONG );
  45. BOOLEAN WINAPI RegGetCitrixVersion(WCHAR *, PULONG);
  46. BOOLEAN IsWallPaperDisabled( HKEY );
  47. /*
  48. * procedures used
  49. */
  50. DWORD GetNumValue( HKEY, LPWSTR, DWORD );
  51. DWORD GetNumValueEx( HKEY, LPWSTR, DWORD, DWORD );
  52. LONG GetStringValue( HKEY, LPWSTR, LPWSTR, LPWSTR, DWORD );
  53. LONG GetStringValueEx( HKEY, LPWSTR, DWORD, LPWSTR, LPWSTR, DWORD );
  54. VOID UnicodeToAnsi( CHAR *, ULONG, WCHAR * );
  55. /*******************************************************************************
  56. *
  57. * QueryWinStaCreate
  58. *
  59. * query WINSTATIONCREATE structure
  60. *
  61. * ENTRY:
  62. *
  63. * Handle (input)
  64. * registry handle
  65. * pCreate (output)
  66. * address to return WINSTATIONCREATE structure
  67. *
  68. * EXIT:
  69. * nothing
  70. *
  71. ******************************************************************************/
  72. VOID
  73. QueryWinStaCreate( HKEY Handle,
  74. PWINSTATIONCREATE pCreate )
  75. {
  76. pCreate->fEnableWinStation = (BOOLEAN) GetNumValue( Handle,
  77. WIN_ENABLEWINSTATION,
  78. TRUE );
  79. pCreate->MaxInstanceCount = GetNumValue( Handle,
  80. WIN_MAXINSTANCECOUNT,
  81. 1 );
  82. }
  83. /*******************************************************************************
  84. *
  85. * QueryUserConfig
  86. *
  87. * query USERCONFIG structure
  88. *
  89. * ENTRY:
  90. *
  91. * Handle (input)
  92. * registry handle
  93. * pUser (input)
  94. * pointer to USERCONFIG structure
  95. *
  96. * EXIT:
  97. * nothing
  98. *
  99. ******************************************************************************/
  100. VOID
  101. QueryUserConfig( HKEY Handle,
  102. PUSERCONFIG pUser )
  103. {
  104. UCHAR seed;
  105. UNICODE_STRING UnicodePassword;
  106. WCHAR encPassword[ PASSWORD_LENGTH + 2 ];
  107. pUser->fInheritAutoLogon =
  108. (BOOLEAN) GetNumValue( Handle, WIN_INHERITAUTOLOGON, TRUE );
  109. pUser->fInheritResetBroken =
  110. (BOOLEAN) GetNumValue( Handle, WIN_INHERITRESETBROKEN, TRUE );
  111. pUser->fInheritReconnectSame =
  112. (BOOLEAN) GetNumValue( Handle, WIN_INHERITRECONNECTSAME, TRUE );
  113. pUser->fInheritInitialProgram =
  114. (BOOLEAN) GetNumValue( Handle, WIN_INHERITINITIALPROGRAM, TRUE );
  115. pUser->fInheritCallback =
  116. (BOOLEAN) GetNumValue( Handle, WIN_INHERITCALLBACK, FALSE );
  117. pUser->fInheritCallbackNumber =
  118. (BOOLEAN) GetNumValue( Handle, WIN_INHERITCALLBACKNUMBER, TRUE );
  119. pUser->fInheritShadow =
  120. (BOOLEAN) GetNumValue( Handle, WIN_INHERITSHADOW, TRUE );
  121. pUser->fInheritMaxSessionTime =
  122. (BOOLEAN) GetNumValue( Handle, WIN_INHERITMAXSESSIONTIME, TRUE );
  123. pUser->fInheritMaxDisconnectionTime =
  124. (BOOLEAN) GetNumValue( Handle, WIN_INHERITMAXDISCONNECTIONTIME, TRUE );
  125. pUser->fInheritMaxIdleTime =
  126. (BOOLEAN) GetNumValue( Handle, WIN_INHERITMAXIDLETIME, TRUE );
  127. pUser->fInheritAutoClient =
  128. (BOOLEAN) GetNumValue( Handle, WIN_INHERITAUTOCLIENT, TRUE );
  129. pUser->fInheritSecurity =
  130. (BOOLEAN) GetNumValue( Handle, WIN_INHERITSECURITY, FALSE );
  131. //NA 2/23/01
  132. pUser->fInheritColorDepth =
  133. (BOOLEAN) GetNumValue( Handle, WIN_INHERITCOLORDEPTH, TRUE );
  134. pUser->fPromptForPassword =
  135. (BOOLEAN) GetNumValue( Handle, WIN_PROMPTFORPASSWORD, FALSE );
  136. pUser->fResetBroken =
  137. (BOOLEAN) GetNumValue( Handle, WIN_RESETBROKEN, FALSE );
  138. pUser->fReconnectSame =
  139. (BOOLEAN) GetNumValue( Handle, WIN_RECONNECTSAME, FALSE );
  140. pUser->fLogonDisabled =
  141. (BOOLEAN) GetNumValue( Handle, WIN_LOGONDISABLED, FALSE );
  142. pUser->fAutoClientDrives =
  143. (BOOLEAN) GetNumValue( Handle, WIN_AUTOCLIENTDRIVES, TRUE );
  144. pUser->fAutoClientLpts =
  145. (BOOLEAN) GetNumValue( Handle, WIN_AUTOCLIENTLPTS, TRUE );
  146. pUser->fForceClientLptDef =
  147. (BOOLEAN) GetNumValue( Handle, WIN_FORCECLIENTLPTDEF, TRUE );
  148. pUser->fDisableEncryption =
  149. (BOOLEAN) GetNumValue( Handle, WIN_DISABLEENCRYPTION, TRUE );
  150. pUser->fHomeDirectoryMapRoot =
  151. (BOOLEAN) GetNumValue( Handle, WIN_HOMEDIRECTORYMAPROOT, FALSE );
  152. pUser->fUseDefaultGina =
  153. (BOOLEAN) GetNumValue( Handle, WIN_USEDEFAULTGINA, FALSE );
  154. pUser->fDisableCpm =
  155. (BOOLEAN) GetNumValue( Handle, WIN_DISABLECPM, FALSE );
  156. pUser->fDisableCdm =
  157. (BOOLEAN) GetNumValue( Handle, WIN_DISABLECDM, FALSE );
  158. pUser->fDisableCcm =
  159. (BOOLEAN) GetNumValue( Handle, WIN_DISABLECCM, FALSE );
  160. pUser->fDisableLPT =
  161. (BOOLEAN) GetNumValue( Handle, WIN_DISABLELPT, FALSE );
  162. pUser->fDisableClip =
  163. (BOOLEAN) GetNumValue( Handle, WIN_DISABLECLIP, FALSE );
  164. pUser->fDisableExe =
  165. (BOOLEAN) GetNumValue( Handle, WIN_DISABLEEXE, FALSE );
  166. pUser->fDisableCam =
  167. (BOOLEAN) GetNumValue( Handle, WIN_DISABLECAM, FALSE );
  168. GetStringValue( Handle, WIN_USERNAME, NULL, pUser->UserName,
  169. USERNAME_LENGTH + 1 );
  170. GetStringValue( Handle, WIN_DOMAIN, NULL, pUser->Domain,
  171. DOMAIN_LENGTH + 1 );
  172. // pull encrypted password out of registry
  173. GetStringValue( Handle, WIN_PASSWORD, NULL, encPassword,
  174. PASSWORD_LENGTH + 2 );
  175. // check for password if there is one then decrypt it
  176. if ( wcslen( encPassword ) ) {
  177. // generate unicode string
  178. RtlInitUnicodeString( &UnicodePassword, &encPassword[1] );
  179. // decrypt password in place
  180. seed = (UCHAR) encPassword[0];
  181. RtlRunDecodeUnicodeString( seed, &UnicodePassword );
  182. // pull clear text password
  183. RtlMoveMemory( pUser->Password, &encPassword[1], sizeof(pUser->Password) );
  184. }
  185. else {
  186. // set to null
  187. pUser->Password[0] = (WCHAR) NULL;
  188. }
  189. GetStringValue( Handle, WIN_WORKDIRECTORY, NULL, pUser->WorkDirectory,
  190. DIRECTORY_LENGTH + 1 );
  191. GetStringValue( Handle, WIN_INITIALPROGRAM, NULL, pUser->InitialProgram,
  192. INITIALPROGRAM_LENGTH + 1 );
  193. GetStringValue( Handle, WIN_CALLBACKNUMBER, NULL, pUser->CallbackNumber,
  194. CALLBACK_LENGTH + 1 );
  195. pUser->Callback = GetNumValue( Handle, WIN_CALLBACK, Callback_Disable );
  196. pUser->Shadow = GetNumValue( Handle, WIN_SHADOW, Shadow_EnableInputNotify );
  197. pUser->MaxConnectionTime = GetNumValue( Handle, WIN_MAXCONNECTIONTIME, 0 );
  198. pUser->MaxDisconnectionTime = GetNumValue( Handle,
  199. WIN_MAXDISCONNECTIONTIME, 0 );
  200. pUser->MaxIdleTime = GetNumValue( Handle, WIN_MAXIDLETIME, 0 );
  201. pUser->KeyboardLayout = GetNumValue( Handle, WIN_KEYBOARDLAYOUT, 0 );
  202. pUser->MinEncryptionLevel = (BYTE) GetNumValue( Handle, WIN_MINENCRYPTIONLEVEL, 1 );
  203. pUser->fWallPaperDisabled = (BOOLEAN) IsWallPaperDisabled( Handle );
  204. GetStringValue( Handle, WIN_NWLOGONSERVER, NULL, pUser->NWLogonServer,
  205. NASIFILESERVER_LENGTH + 1 );
  206. GetStringValue( Handle, WIN_WFPROFILEPATH, NULL, pUser->WFProfilePath,
  207. DIRECTORY_LENGTH + 1 );
  208. GetStringValue( Handle, WIN_WFHOMEDIR, NULL, pUser->WFHomeDir,
  209. DIRECTORY_LENGTH + 1 );
  210. GetStringValue( Handle, WIN_WFHOMEDIRDRIVE, NULL, pUser->WFHomeDirDrive,
  211. 4 );
  212. pUser->ColorDepth = GetNumValue( Handle, POLICY_TS_COLOR_DEPTH, TS_8BPP_SUPPORT );
  213. }
  214. /*******************************************************************************
  215. *
  216. * QueryConfig
  217. *
  218. * query WINSTATIONCONFIG structure
  219. *
  220. * ENTRY:
  221. *
  222. * Handle (input)
  223. * registry handle
  224. * pConfig (output)
  225. * address to return WINSTATIONCONFIG structure
  226. *
  227. * EXIT:
  228. * nothing
  229. *
  230. ******************************************************************************/
  231. VOID
  232. QueryConfig( HKEY Handle,
  233. PWINSTATIONCONFIG pConfig )
  234. {
  235. GetStringValue( Handle, WIN_COMMENT, NULL, pConfig->Comment,
  236. WINSTATIONCOMMENT_LENGTH + 1 );
  237. QueryUserConfig( Handle, &pConfig->User );
  238. (void) RegQueryOEMId( pConfig->OEMId, sizeof(pConfig->OEMId) );
  239. }
  240. /*******************************************************************************
  241. *
  242. * QueryNetwork
  243. *
  244. * Query NETWORKCONFIG structure
  245. *
  246. * ENTRY:
  247. *
  248. * Handle (input)
  249. * registry handle
  250. * pNetwork (output)
  251. * address to return NETWORKCONFIG structure
  252. *
  253. * EXIT:
  254. * nothing
  255. *
  256. ******************************************************************************/
  257. VOID
  258. QueryNetwork( HKEY Handle,
  259. PNETWORKCONFIG pNetwork )
  260. {
  261. pNetwork->LanAdapter = GetNumValue( Handle, WIN_LANADAPTER, 0 );
  262. }
  263. /*******************************************************************************
  264. *
  265. * QueryNasi
  266. *
  267. * Query NASICONFIG structure
  268. *
  269. * ENTRY:
  270. *
  271. * Handle (input)
  272. * registry handle
  273. * pNasi (output)
  274. * address to return NASICONFIG structure
  275. *
  276. * EXIT:
  277. * nothing
  278. *
  279. ******************************************************************************/
  280. VOID
  281. QueryNasi( HKEY Handle,
  282. PNASICONFIG pNasi )
  283. {
  284. UCHAR seed;
  285. UNICODE_STRING UnicodePassword;
  286. WCHAR encPassword[ NASIPASSWORD_LENGTH + 2 ];
  287. // pull encrypted password out of registry
  288. GetStringValue( Handle, WIN_NASIPASSWORD, NULL, encPassword,
  289. NASIPASSWORD_LENGTH + 1 );
  290. // check for password if there is one then decrypt it
  291. if ( wcslen( encPassword ) ) {
  292. // generate unicode string
  293. RtlInitUnicodeString( &UnicodePassword, &encPassword[1] );
  294. // decrypt password in place
  295. seed = (UCHAR) encPassword[0];
  296. RtlRunDecodeUnicodeString( seed, &UnicodePassword );
  297. // pull clear text password
  298. RtlMoveMemory( pNasi->PassWord, &encPassword[1], sizeof(pNasi->PassWord) );
  299. }
  300. else {
  301. // set to null
  302. pNasi->PassWord[0] = (WCHAR) NULL;
  303. }
  304. GetStringValue( Handle, WIN_NASISPECIFICNAME, NULL, pNasi->SpecificName,
  305. NASISPECIFICNAME_LENGTH + 1 );
  306. GetStringValue( Handle, WIN_NASIUSERNAME, NULL, pNasi->UserName,
  307. NASIUSERNAME_LENGTH + 1 );
  308. GetStringValue( Handle, WIN_NASISESSIONNAME, NULL, pNasi->SessionName,
  309. NASISESSIONNAME_LENGTH + 1 );
  310. GetStringValue( Handle, WIN_NASIFILESERVER, NULL, pNasi->FileServer,
  311. NASIFILESERVER_LENGTH + 1 );
  312. pNasi->GlobalSession = (BOOLEAN)GetNumValue( Handle, WIN_NASIGLOBALSESSION, 0 );
  313. }
  314. /*******************************************************************************
  315. *
  316. * QueryAsync
  317. *
  318. * query ASYNCCONFIG structure
  319. *
  320. * ENTRY:
  321. *
  322. * Handle (input)
  323. * registry handle
  324. * pAsync (output)
  325. * address to return ASYNCCONFIG structure
  326. *
  327. * EXIT:
  328. * nothing
  329. *
  330. ******************************************************************************/
  331. VOID
  332. QueryAsync( HKEY Handle,
  333. PASYNCCONFIG pAsync )
  334. {
  335. GetStringValue( Handle, WIN_DEVICENAME, NULL, pAsync->DeviceName,
  336. DEVICENAME_LENGTH + 1 );
  337. GetStringValue( Handle, WIN_MODEMNAME, NULL, pAsync->ModemName,
  338. MODEMNAME_LENGTH + 1 );
  339. pAsync->BaudRate = GetNumValue( Handle, WIN_BAUDRATE, 9600 );
  340. pAsync->Parity = GetNumValue( Handle, WIN_PARITY, NOPARITY );
  341. pAsync->StopBits = GetNumValue( Handle, WIN_STOPBITS, ONESTOPBIT );
  342. pAsync->ByteSize = GetNumValue( Handle, WIN_BYTESIZE, 8 );
  343. pAsync->fEnableDsrSensitivity = (BOOLEAN) GetNumValue( Handle,
  344. WIN_ENABLEDSRSENSITIVITY,
  345. FALSE );
  346. pAsync->fConnectionDriver = (BOOLEAN) GetNumValue( Handle,
  347. WIN_CONNECTIONDRIVER,
  348. FALSE );
  349. QueryFlow( Handle, &pAsync->FlowControl );
  350. QueryConnect( Handle, &pAsync->Connect );
  351. }
  352. /*******************************************************************************
  353. *
  354. * QueryOemTd
  355. *
  356. * Query OEMTDCONFIG structure
  357. *
  358. * ENTRY:
  359. *
  360. * Handle (input)
  361. * registry handle
  362. * pOemTd (output)
  363. * address to return OEMTDCONFIG structure
  364. *
  365. * EXIT:
  366. * nothing
  367. *
  368. ******************************************************************************/
  369. VOID
  370. QueryOemTd( HKEY Handle,
  371. POEMTDCONFIG pOemTd )
  372. {
  373. pOemTd->Adapter = GetNumValue( Handle, WIN_OEMTDADAPTER, 0 );
  374. GetStringValue( Handle, WIN_OEMTDDEVICENAME, NULL, pOemTd->DeviceName,
  375. DEVICENAME_LENGTH + 1 );
  376. pOemTd->Flags = GetNumValue( Handle, WIN_OEMTDFLAGS, 0 );
  377. }
  378. /*******************************************************************************
  379. *
  380. * QueryFlow
  381. *
  382. * query FLOWCONTROLCONFIG structure
  383. *
  384. * ENTRY:
  385. *
  386. * Handle (input)
  387. * registry handle
  388. * pFlow (output)
  389. * address to return FLOWCONTROLCONFIG structure
  390. *
  391. * EXIT:
  392. * nothing
  393. *
  394. ******************************************************************************/
  395. VOID
  396. QueryFlow( HKEY Handle,
  397. PFLOWCONTROLCONFIG pFlow )
  398. {
  399. pFlow->fEnableSoftwareRx = (BOOLEAN) GetNumValue( Handle,
  400. WIN_FLOWSOFTWARERX,
  401. FALSE );
  402. pFlow->fEnableSoftwareTx = (BOOLEAN) GetNumValue( Handle,
  403. WIN_FLOWSOFTWARETX,
  404. TRUE );
  405. pFlow->fEnableDTR = (BOOLEAN) GetNumValue( Handle, WIN_ENABLEDTR, TRUE );
  406. pFlow->fEnableRTS = (BOOLEAN) GetNumValue( Handle, WIN_ENABLERTS, TRUE );
  407. pFlow->XonChar = (UCHAR) GetNumValue( Handle, WIN_XONCHAR, 0 );
  408. pFlow->XoffChar = (UCHAR) GetNumValue( Handle, WIN_XOFFCHAR, 0 );
  409. pFlow->Type = GetNumValue( Handle, WIN_FLOWTYPE, FlowControl_Hardware );
  410. pFlow->HardwareReceive = GetNumValue( Handle, WIN_FLOWHARDWARERX,
  411. ReceiveFlowControl_RTS );
  412. pFlow->HardwareTransmit = GetNumValue( Handle, WIN_FLOWHARDWARETX,
  413. TransmitFlowControl_CTS );
  414. }
  415. /*******************************************************************************
  416. *
  417. * QueryConnect
  418. *
  419. * query CONNECTCONFIG structure
  420. *
  421. * ENTRY:
  422. *
  423. * Handle (input)
  424. * registry handle
  425. * pConnect (output)
  426. * address to return CONNECTCONFIG structure
  427. *
  428. * EXIT:
  429. * nothing
  430. *
  431. ******************************************************************************/
  432. VOID
  433. QueryConnect( HKEY Handle,
  434. PCONNECTCONFIG pConnect )
  435. {
  436. pConnect->Type = GetNumValue( Handle, WIN_CONNECTTYPE, Connect_DSR );
  437. pConnect->fEnableBreakDisconnect = (BOOLEAN) GetNumValue( Handle,
  438. WIN_ENABLEBREAKDISCONNECT,
  439. FALSE );
  440. }
  441. /*******************************************************************************
  442. *
  443. * QueryCd
  444. *
  445. * query CDCONFIG structure
  446. *
  447. * ENTRY:
  448. *
  449. * Handle (input)
  450. * registry handle
  451. * pCdConfig (output)
  452. * address to return CDCONFIG structure
  453. *
  454. * EXIT:
  455. * nothing
  456. *
  457. ******************************************************************************/
  458. VOID
  459. QueryCd( HKEY Handle,
  460. PCDCONFIG pCdConfig )
  461. {
  462. pCdConfig->CdClass = GetNumValue( Handle, WIN_CDCLASS, CdNone );
  463. GetStringValue( Handle, WIN_CDNAME, NULL, pCdConfig->CdName,
  464. CDNAME_LENGTH + 1 );
  465. GetStringValue( Handle, WIN_CDDLL, L"", pCdConfig->CdDLL,
  466. DLLNAME_LENGTH + 1 );
  467. pCdConfig->CdFlag = GetNumValue( Handle, WIN_CDFLAG, 0 );
  468. }
  469. /*******************************************************************************
  470. *
  471. * QueryWd
  472. *
  473. * query WDCONFIG structure
  474. *
  475. * ENTRY:
  476. *
  477. * Handle (input)
  478. * registry handle
  479. * pWd (output)
  480. * address to return WDCONFIG structure
  481. *
  482. * EXIT:
  483. * nothing
  484. *
  485. ******************************************************************************/
  486. VOID
  487. QueryWd( HKEY Handle,
  488. PWDCONFIG pWd )
  489. {
  490. GetStringValue( Handle, WIN_WDNAME, NULL, pWd->WdName, WDNAME_LENGTH + 1 );
  491. GetStringValue( Handle, WIN_WDDLL, L"", pWd->WdDLL, DLLNAME_LENGTH + 1 );
  492. GetStringValue( Handle, WIN_WSXDLL, NULL, pWd->WsxDLL, DLLNAME_LENGTH + 1 );
  493. pWd->WdFlag = GetNumValue( Handle, WIN_WDFLAG, 0 );
  494. pWd->WdInputBufferLength = GetNumValue( Handle, WIN_INPUTBUFFERLENGTH, 2048 );
  495. GetStringValue( Handle, WIN_CFGDLL, NULL, pWd->CfgDLL, DLLNAME_LENGTH + 1 );
  496. GetStringValue( Handle, WIN_WDPREFIX, NULL, pWd->WdPrefix, WDPREFIX_LENGTH + 1 );
  497. }
  498. /*******************************************************************************
  499. *
  500. * QueryPdConfig
  501. *
  502. * query PDCONFIG structure
  503. *
  504. * ENTRY:
  505. *
  506. * Handle (input)
  507. * registry handle
  508. * pConfig (output)
  509. * address to return array of PDCONFIG structures
  510. * pCount (input/output)
  511. * pointer to number of PDCONFIG array elements
  512. *
  513. * EXIT:
  514. * nothing
  515. *
  516. ******************************************************************************/
  517. VOID
  518. QueryPdConfig( HKEY Handle,
  519. PPDCONFIG pConfig,
  520. PULONG pCount )
  521. {
  522. ULONG i;
  523. for ( i=0; i < *pCount; i++ ) {
  524. QueryPdConfig2( Handle, &pConfig[i].Create, i );
  525. QueryPdParams( Handle,
  526. pConfig[i].Create.SdClass,
  527. &pConfig[i].Params );
  528. }
  529. *pCount = MAX_PDCONFIG;
  530. }
  531. /*******************************************************************************
  532. *
  533. * QueryPdConfig2
  534. *
  535. * query PDCONFIG2 structure
  536. *
  537. * ENTRY:
  538. *
  539. * Handle (input)
  540. * registry handle
  541. * pPd2 (output)
  542. * address to return PDCONFIG2 structure
  543. * Index (input)
  544. * Index (array index)
  545. *
  546. * EXIT:
  547. * nothing
  548. *
  549. ******************************************************************************/
  550. VOID
  551. QueryPdConfig2( HKEY Handle,
  552. PPDCONFIG2 pPd2,
  553. ULONG Index )
  554. {
  555. GetStringValueEx( Handle, WIN_PDNAME, Index,
  556. NULL, pPd2->PdName, PDNAME_LENGTH + 1 );
  557. pPd2->SdClass = GetNumValueEx( Handle, WIN_PDCLASS, Index, Index==0 ? SdAsync : SdNone );
  558. GetStringValueEx( Handle, WIN_PDDLL, Index,
  559. NULL, pPd2->PdDLL, DLLNAME_LENGTH + 1 );
  560. pPd2->PdFlag = GetNumValueEx( Handle, WIN_PDFLAG, Index, 0 );
  561. /*
  562. * The following data is the same for all pds
  563. */
  564. pPd2->OutBufLength = GetNumValue( Handle, WIN_OUTBUFLENGTH, 530 );
  565. pPd2->OutBufCount = GetNumValue( Handle, WIN_OUTBUFCOUNT, 10 );
  566. pPd2->OutBufDelay = GetNumValue( Handle, WIN_OUTBUFDELAY, 100 );
  567. pPd2->InteractiveDelay = GetNumValue( Handle, WIN_INTERACTIVEDELAY, 10 );
  568. pPd2->KeepAliveTimeout = GetNumValue( Handle, WIN_KEEPALIVETIMEOUT, 0 );
  569. pPd2->PortNumber = GetNumValue( Handle, WIN_PORTNUMBER, 0 );
  570. }
  571. /*******************************************************************************
  572. *
  573. * QueryPdConfig3
  574. *
  575. * query PDCONFIG3 structure
  576. *
  577. * ENTRY:
  578. *
  579. * Handle (input)
  580. * registry handle
  581. * pPd (output)
  582. * address to return PDCONFIG3 structure
  583. * Index (input)
  584. * Index (array index)
  585. *
  586. * EXIT:
  587. * nothing
  588. *
  589. ******************************************************************************/
  590. VOID
  591. QueryPdConfig3( HKEY Handle,
  592. PPDCONFIG3 pPd3,
  593. ULONG Index )
  594. {
  595. int i;
  596. ULONG Length;
  597. LPWSTR tmp;
  598. WCHAR PdName[ MAX_PDCONFIG * ( PDNAME_LENGTH + 1 ) + 1 ];
  599. ULONG ValueType;
  600. QueryPdConfig2( Handle, &pPd3->Data, Index );
  601. GetStringValue( Handle, WIN_SERVICENAME, NULL,
  602. pPd3->ServiceName,
  603. PDNAME_LENGTH + 1 );
  604. GetStringValue( Handle, WIN_CONFIGDLL, NULL,
  605. pPd3->ConfigDLL,
  606. DLLNAME_LENGTH + 1 );
  607. Length = sizeof(PdName);
  608. pPd3->RequiredPdCount = 0;
  609. if ( RegQueryValueEx( Handle, WIN_REQUIREDPDS, NULL, &ValueType,
  610. (LPBYTE)PdName, &Length ) == ERROR_SUCCESS ) {
  611. tmp = PdName;
  612. i = 0;
  613. while ( *tmp != UNICODE_NULL ) {
  614. pPd3->RequiredPdCount++;
  615. wcscpy( pPd3->RequiredPds[i], tmp );
  616. i++;
  617. tmp += wcslen(tmp) + 1;
  618. }
  619. }
  620. }
  621. /*******************************************************************************
  622. *
  623. * QueryPdParams
  624. *
  625. * query PDPARAMS structure
  626. *
  627. * ENTRY:
  628. *
  629. * Handle (input)
  630. * registry handle
  631. * SdClass (input)
  632. * type of PD
  633. * pParams (output)
  634. * address to return PDPARAMS structure
  635. *
  636. * EXIT:
  637. * nothing
  638. *
  639. ******************************************************************************/
  640. VOID
  641. QueryPdParams( HKEY Handle,
  642. SDCLASS SdClass,
  643. PPDPARAMS pParams )
  644. {
  645. pParams->SdClass = SdClass;
  646. switch ( SdClass ) {
  647. case SdNetwork :
  648. QueryNetwork( Handle, &pParams->Network );
  649. break;
  650. case SdNasi :
  651. QueryNasi( Handle, &pParams->Nasi );
  652. break;
  653. case SdAsync :
  654. QueryAsync( Handle, &pParams->Async );
  655. break;
  656. case SdOemTransport :
  657. QueryOemTd( Handle, &pParams->OemTd );
  658. break;
  659. }
  660. }
  661. #define CONTROL_PANEL L"Control Panel"
  662. #define DESKTOP L"Desktop"
  663. #define WALLPAPER L"Wallpaper"
  664. #define NONE L"(None)"
  665. /*******************************************************************************
  666. *
  667. * IsWallPaperDisabled
  668. *
  669. * Is the wall paper disabled?
  670. *
  671. * ENTRY:
  672. * Handle (input)
  673. * registry handle
  674. * EXIT:
  675. * TRUE or FALSE (returns FALSE as default)
  676. *
  677. ******************************************************************************/
  678. BOOLEAN IsWallPaperDisabled( HKEY Handle )
  679. {
  680. HKEY Handle1;
  681. WCHAR KeyString[256];
  682. wcscpy( KeyString, WIN_USEROVERRIDE );
  683. wcscat( KeyString, L"\\" );
  684. wcscat( KeyString, CONTROL_PANEL );
  685. wcscat( KeyString, L"\\" );
  686. wcscat( KeyString, DESKTOP );
  687. if ( RegOpenKeyEx( Handle, KeyString, 0, KEY_READ,
  688. &Handle1 ) != ERROR_SUCCESS )
  689. return FALSE;
  690. GetStringValue( Handle1, WALLPAPER, NULL, KeyString, 256 );
  691. RegCloseKey( Handle1 );
  692. if( KeyString[0] == 0 || ( _wcsicmp( NONE, KeyString ) == 0 ) )
  693. {
  694. return TRUE;
  695. }
  696. return FALSE;
  697. }
  698. /*****************************************************************************
  699. *
  700. * RegBuildNumberQuery
  701. *
  702. * Query the current build number from the registry.
  703. *
  704. * HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\Current Version\
  705. * CurrentBuildNumber:REG_SZ:129
  706. *
  707. * ENTRY:
  708. * Param1 (input/output)
  709. * Comments
  710. *
  711. * EXIT:
  712. * STATUS_SUCCESS - no error
  713. *
  714. ****************************************************************************/
  715. BOOLEAN WINAPI
  716. RegBuildNumberQuery(
  717. PULONG pBuildNum
  718. )
  719. {
  720. ULONG Result, Value;
  721. HKEY hKey;
  722. WCHAR Buf[256];
  723. Result = RegOpenKeyEx(
  724. HKEY_LOCAL_MACHINE,
  725. BUILD_NUMBER_KEY,
  726. 0, // Reserved
  727. KEY_READ,
  728. &hKey
  729. );
  730. if( Result != ERROR_SUCCESS ) {
  731. #if DBG
  732. DbgPrint("RegBuildNumberQuery: Failed to open key %ws\n",BUILD_NUMBER_KEY);
  733. #endif
  734. return( FALSE );
  735. }
  736. Result = GetStringValue(
  737. hKey,
  738. BUILD_NUMBER_VALUE,
  739. L"0",
  740. Buf,
  741. sizeof(Buf)
  742. );
  743. if( Result != ERROR_SUCCESS ) {
  744. #if DBG
  745. DbgPrint("RegBuildNumberQuery: Failed to query value %ws\n",BUILD_NUMBER_VALUE);
  746. #endif
  747. RegCloseKey( hKey );
  748. return( FALSE );
  749. }
  750. RegCloseKey( hKey );
  751. //
  752. // Now must convert it into a number
  753. //
  754. Value = 0;
  755. swscanf( Buf, L"%d", &Value );
  756. *pBuildNum = Value;
  757. return( TRUE );
  758. }
  759. /*******************************************************************************
  760. *
  761. * RegQueryOEMId
  762. *
  763. * query oem id
  764. *
  765. * ENTRY:
  766. *
  767. * pOEMId (output)
  768. * pointer to buffer to return oem id
  769. * Length (input)
  770. * length of buffer
  771. *
  772. * EXIT:
  773. *
  774. * TRUE -- The operation succeeded.
  775. *
  776. * FALSE -- The operation failed. Extended error status is available
  777. * using GetLastError.
  778. *
  779. ******************************************************************************/
  780. BOOLEAN
  781. RegQueryOEMId( PBYTE pOEMId, ULONG Length )
  782. {
  783. HKEY Handle2;
  784. WCHAR OEMIdW[10];
  785. /*
  786. * Open registry (LOCAL_MACHINE\....\Terminal Server)
  787. */
  788. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
  789. KEY_READ, &Handle2 ) == ERROR_SUCCESS ) {
  790. GetStringValue( Handle2, REG_CITRIX_OEMID, NULL, OEMIdW, 10 );
  791. UnicodeToAnsi( pOEMId, Length, OEMIdW );
  792. pOEMId[3] = '\0';
  793. RegCloseKey( Handle2 );
  794. }
  795. return( TRUE );
  796. }
  797. /*******************************************************************************
  798. *
  799. * RegGetTServerVersion (UNICODE)
  800. *
  801. * Get the Terminal Server version number from the specified server.
  802. *
  803. * This version number is changed by Microsoft, and not OEM's.
  804. *
  805. * ENTRY:
  806. * pServerName (input)
  807. * Points to string of server to check.
  808. *
  809. * EXIT:
  810. * TRUE if Hydra Terminal Server; FALSE otherwise
  811. *
  812. ******************************************************************************/
  813. BOOLEAN WINAPI
  814. RegGetTServerVersion(
  815. WCHAR * pServerName,
  816. PULONG pVersionNumber
  817. )
  818. {
  819. LONG Error;
  820. HKEY ServerHandle, UserHandle;
  821. ULONG Value;
  822. /*
  823. * Connect to registry of specified server.
  824. */
  825. if ( (Error = RegConnectRegistry( pServerName,
  826. HKEY_LOCAL_MACHINE,
  827. &ServerHandle )) != ERROR_SUCCESS )
  828. return( FALSE );
  829. /*
  830. * Open the Terminal Server key and get the Version value.
  831. */
  832. if ( (Error = RegOpenKeyEx( ServerHandle, REG_CONTROL_TSERVER, 0,
  833. KEY_READ, &UserHandle )) != ERROR_SUCCESS ) {
  834. RegCloseKey( ServerHandle );
  835. return( FALSE );
  836. }
  837. Value = GetNumValue(
  838. UserHandle,
  839. REG_CITRIX_VERSION,
  840. 0 );
  841. /*
  842. * Close registry handles.
  843. */
  844. RegCloseKey( UserHandle );
  845. RegCloseKey( ServerHandle );
  846. *pVersionNumber = Value;
  847. return( TRUE );
  848. }
  849. /*******************************************************************************
  850. *
  851. * RegQueryUtilityCommandList (UNICODE)
  852. *
  853. * Allocate and build an array of PROGRAMCALL structures for the specified
  854. * MultiUser utility.
  855. *
  856. * ENTRY:
  857. * pUtilityKey (input)
  858. * Points to string containing the utility's command registry key.
  859. * ppProgramCall (output)
  860. * Points to a PPROGRAMCALL variable that will be set to the API-allocated
  861. * array of PROGRAMCALL structures, containing n elements, where n =
  862. * number of commands supported by the utility (as specified in the
  863. * registry). The pFirst item of array element 0 will point to the
  864. * first command (sorted alphabetically by command name). The pNext items
  865. * are then used to walk the list, till pNext is NULL.
  866. *
  867. * EXIT:
  868. * ERROR_SUCCESS if all goes well;
  869. * An error code is returned if failure.
  870. *
  871. * If success, the caller must call RegFreeUtilityCommandList with the
  872. * ppProgramCall variable to free the PROGRAMCALL structure array when
  873. * finished using the array.
  874. *
  875. * The format of the REG_MULTI_SZ command item in the registry is as follows:
  876. *
  877. * string 1: "0" or "1" (required)
  878. *
  879. * 0 specifies that the command is a normal command which will
  880. * be presented as an option by the utility USAGE help. 1
  881. * indicates a command alias (hidden option), which won't
  882. * appear in USAGE help.
  883. *
  884. * string 2: "number" (required)
  885. *
  886. * Specifies the minimum number of characters that must be
  887. * typed for the command to be recognized (base 10).
  888. *
  889. * string 3: "command" (required)
  890. *
  891. * This is the actual command that will be recognized and
  892. * displayed in the USAGE help (if not an aliased command).
  893. *
  894. * string 4: "program" (required)
  895. *
  896. * The file name of the program that will be executed. This
  897. * should be a standard name.extension filename, and can
  898. * include a full path, although this is not necessary since
  899. * the utilities will normally reside in the standard SYSTEM32
  900. * directory, which is a part of the standard PATH.
  901. *
  902. * string 5: "extra args" (optional)
  903. *
  904. * If specified, this string will be passed along to the
  905. * utilsub.lib ExecProgram API to specify additional
  906. * hard-coded arguments that will be used, in addition to any
  907. * other arguments that were specified by the user on the
  908. * command line.
  909. *
  910. * Note: If the command item is not a REG_MULTI_SZ value, or the command item
  911. * is a REG_MULTI_SZ item but there is an error in its format, that
  912. * command will be omitted from the command list. The return value
  913. * from this function will still be ERROR_SUCCESS, but the command in
  914. * error will be ignored by the utilities.
  915. *
  916. ******************************************************************************/
  917. LONG WINAPI
  918. RegQueryUtilityCommandList(
  919. LPWSTR pUtilityKey,
  920. PPROGRAMCALL * ppProgramCall
  921. )
  922. {
  923. HKEY Handle = NULL;
  924. LONG status = ERROR_SUCCESS;
  925. DWORD iValue, cValues, ccValueName, cbValueData,
  926. ccTmpValueName, cbTmpValueData, dwType;
  927. LPWSTR pValueName = NULL, pValueData = NULL, pString;
  928. PPROGRAMCALL pProg = NULL, pProgNext, pProgPrev;
  929. ULONG ulCommandLen;
  930. PWCHAR pEndptr;
  931. int iCompare;
  932. *ppProgramCall = NULL;
  933. /*
  934. * Open specified utility key and determine number of values and maximum
  935. * value name and data length.
  936. */
  937. if ( status = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  938. pUtilityKey,
  939. 0,
  940. KEY_READ,
  941. &Handle ) != ERROR_SUCCESS ) {
  942. #if DBG
  943. DbgPrint("RegQueryUtilityCommandList: Can't open command list utility key %ws; error = %d\n", pUtilityKey, status);
  944. #endif
  945. goto error;
  946. }
  947. if ( status = RegQueryInfoKey( Handle,
  948. NULL, // lpClass
  949. NULL, // lpcbClass
  950. NULL, // lpReserved
  951. NULL, // lpcSubKeys
  952. NULL, // lpcbMaxSubKeyLen
  953. NULL, // lpcbMaxClassLen
  954. &cValues, // lpcValues
  955. &ccValueName, // lpcbMaxValueNameLen
  956. &cbValueData, // lpcbMaxValueLen
  957. NULL, // lpcbSecurityDescriptor
  958. NULL // lpftLastWriteTime
  959. ) != ERROR_SUCCESS ) {
  960. #if DBG
  961. DbgPrint("RegQueryUtilityCommandList: Can't query info for utility %ws; error = %d\n", pUtilityKey, status);
  962. #endif
  963. goto error;
  964. }
  965. /*
  966. * Allocate space for #values + 1 PROGRAMCALL elements and value name and
  967. * data buffers.
  968. */
  969. if ( ((*ppProgramCall = (PPROGRAMCALL)LocalAlloc( LPTR, (sizeof(PROGRAMCALL) * (cValues+1)) )) == NULL) ||
  970. ((pValueName = (LPWSTR)LocalAlloc( LPTR, (int)(++ccValueName * sizeof(WCHAR)) )) == NULL) ||
  971. ((pValueData = (LPWSTR)LocalAlloc( LPTR, (int)cbValueData )) == NULL) ) {
  972. status = GetLastError();
  973. #if DBG
  974. DbgPrint("RegQueryUtilityCommandList: Can't allocate memory buffer(s) for utility %ws; error = %d\n", pUtilityKey, status);
  975. #endif
  976. goto error;
  977. }
  978. /*
  979. * Enumerate and parse each value into the PROGRAMCALL components.
  980. */
  981. for ( iValue = 0, pProg = *ppProgramCall;
  982. iValue < cValues;
  983. iValue++, pProg++ ) {
  984. ccTmpValueName = ccValueName;
  985. cbTmpValueData = cbValueData;
  986. if ( (status = RegEnumValue( Handle,
  987. iValue,
  988. pValueName,
  989. &ccTmpValueName,
  990. NULL,
  991. &dwType,
  992. (LPBYTE)pValueData,
  993. &cbTmpValueData )) != ERROR_SUCCESS ) {
  994. #if DBG
  995. DbgPrint("RegQueryUtilityCommandList: Can't enumerate command (index = %d) for utility %ws; error = %d\n", iValue, pUtilityKey, status);
  996. #endif
  997. goto error;
  998. }
  999. /*
  1000. * If the data is not REG_MULTI_SZ, ignore it.
  1001. */
  1002. if ( dwType != REG_MULTI_SZ )
  1003. goto CommandInError;
  1004. /*
  1005. * Allocate data storage for this command, then parse and assign
  1006. * to the PROGRAMCALL structure items.
  1007. */
  1008. if ( (pProg->pRegistryMultiString = LocalAlloc(LPTR, cbTmpValueData)) == NULL ) {
  1009. status = GetLastError();
  1010. #if DBG
  1011. DbgPrint("RegQueryUtilityCommandList: Can't allocate memory buffer for utility %ws; error = %d\n", pUtilityKey, status);
  1012. #endif
  1013. goto error;
  1014. }
  1015. memcpy(pProg->pRegistryMultiString, pValueData, cbTmpValueData);
  1016. pString = pProg->pRegistryMultiString;
  1017. /*
  1018. * Parse alias flag.
  1019. */
  1020. if ( !wcscmp(pString, L"1") )
  1021. pProg->fAlias = TRUE;
  1022. else if ( !wcscmp(pString, L"0") )
  1023. pProg->fAlias = FALSE;
  1024. else
  1025. goto CommandInError;
  1026. pString += (wcslen(pString) + 1);
  1027. /*
  1028. * Parse command length.
  1029. */
  1030. if ( *pString == L'\0' )
  1031. goto CommandInError;
  1032. ulCommandLen = wcstoul(pString, &pEndptr, 10);
  1033. if ( *pEndptr != L'\0' )
  1034. goto CommandInError;
  1035. pProg->CommandLen = (USHORT)ulCommandLen;
  1036. pString += (wcslen(pString) + 1);
  1037. /*
  1038. * Parse command string.
  1039. */
  1040. if ( *pString == L'\0' )
  1041. goto CommandInError;
  1042. pProg->Command = pString;
  1043. pString += (wcslen(pString) + 1);
  1044. /*
  1045. * Parse program string.
  1046. */
  1047. if ( *pString == L'\0' )
  1048. goto CommandInError;
  1049. pProg->Program = pString;
  1050. pString += (wcslen(pString) + 1);
  1051. /*
  1052. * Parse (optional) Args string.
  1053. */
  1054. if ( *pString != L'\0' )
  1055. pProg->Args = pString;
  1056. /*
  1057. * Walk the command list to link this item in it's proper
  1058. * sorted place.
  1059. */
  1060. if ( pProg == *ppProgramCall ) {
  1061. pProg->pFirst = pProg; // first item in the list
  1062. } else for ( pProgPrev = pProgNext = (*ppProgramCall)->pFirst; ; ) {
  1063. if ( (iCompare = _wcsicmp(pProg->Command, pProgNext->Command)) < 0 ) {
  1064. pProg->pNext = pProgNext; // point to next
  1065. if ( pProgNext == (*ppProgramCall)->pFirst )
  1066. (*ppProgramCall)->pFirst = pProg; // first item
  1067. else
  1068. pProgPrev->pNext = pProg; // link after previous
  1069. break;
  1070. } else if ( iCompare == 0 ) {
  1071. goto CommandInError; // duplicate command - ignore
  1072. }
  1073. if ( pProgNext->pNext == NULL ) {
  1074. pProgNext->pNext = pProg; // link at end of list
  1075. break;
  1076. } else {
  1077. pProgPrev = pProgNext;
  1078. pProgNext = pProgNext->pNext;
  1079. }
  1080. }
  1081. continue;
  1082. CommandInError:
  1083. /*
  1084. * The command format is in error - ignore it.
  1085. */
  1086. if ( pProg->pRegistryMultiString )
  1087. LocalFree(pProg->pRegistryMultiString);
  1088. memset(pProg, 0, sizeof(PROGRAMCALL));
  1089. pProg--;
  1090. }
  1091. error:
  1092. if ( Handle != NULL )
  1093. RegCloseKey(Handle);
  1094. if ( pValueName )
  1095. LocalFree(pValueName);
  1096. if ( pValueData )
  1097. LocalFree(pValueData);
  1098. if ( status != ERROR_SUCCESS ) {
  1099. if ( *ppProgramCall ) {
  1100. RegFreeUtilityCommandList(*ppProgramCall);
  1101. *ppProgramCall = NULL;
  1102. }
  1103. }
  1104. return( status );
  1105. }
  1106. /*******************************************************************************
  1107. *
  1108. * RegFreeUtilityCommandList (UNICODE)
  1109. *
  1110. * Free the specified array of PROGRAMCALL structures.
  1111. *
  1112. * ENTRY:
  1113. * pProgramCall (input)
  1114. * Points PROGRAMCALL array to free.
  1115. *
  1116. * EXIT:
  1117. * ERROR_SUCCESS if all goes well; error code if failure
  1118. *
  1119. ******************************************************************************/
  1120. LONG WINAPI
  1121. RegFreeUtilityCommandList(
  1122. PPROGRAMCALL pProgramCall
  1123. )
  1124. {
  1125. PPROGRAMCALL pProg;
  1126. LONG status = ERROR_SUCCESS;
  1127. if ( pProgramCall ) {
  1128. for ( pProg = pProgramCall->pFirst; pProg != NULL; pProg = pProg->pNext ) {
  1129. if ( LocalFree( pProg->pRegistryMultiString ) != NULL ) {
  1130. status = GetLastError();
  1131. #if DBG
  1132. DbgPrint("RegFreeUtilityCommandList: Failed to free command list element for %ws; error = %d\n", pProg->Program, status);
  1133. #endif
  1134. }
  1135. }
  1136. if ( LocalFree( pProgramCall ) != NULL ) {
  1137. status = GetLastError();
  1138. #if DBG
  1139. DbgPrint("RegFreeUtilityCommandList: Failed to free command list array; error = %d\n", status);
  1140. #endif
  1141. }
  1142. }
  1143. return( status );
  1144. }