Reactos
at master 831 lines 25 kB view raw
1/* 2* 3* COPYRIGHT: See COPYING in the top level directory 4* PROJECT: ReactOS devmgr.dll 5* FILE: dll/win32/devmgr/api.cpp 6* PURPOSE: devmgr.dll interface 7* PROGRAMMER: Thomas Weidenmueller (w3seek@users.sourceforge.net) 8* Ged Murphy (gedmurphy@reactos.org) 9* NOTES: 10* Some helpful resources: 11* http://support.microsoft.com/default.aspx?scid=kb;%5BLN%5D;815320 12* https://web.archive.org/web/20050321020634/http://www.jsifaq.com/SUBO/tip7400/rh7482.htm 13* http://www.jsiinc.com/SUBM/tip6400/rh6490.htm 14* 15* UPDATE HISTORY: 16* 04-04-2004 Created 17*/ 18 19#include "precomp.h" 20#include "devmgmt/MainWindow.h" 21#include "properties/properties.h" 22 23HINSTANCE hDllInstance = NULL; 24 25 26 27/*************************************************************************** 28* NAME EXPORTED 29* DeviceAdvancedPropertiesW 30* 31* DESCRIPTION 32* Invokes the device properties dialog, this version may add some property pages 33* for some devices 34* 35* ARGUMENTS 36* hWndParent: Handle to the parent window 37* lpMachineName: Machine Name, NULL is the local machine 38* lpDeviceID: Specifies the device whose properties are to be shown 39* 40* RETURN VALUE 41* Always returns -1, a call to GetLastError returns 0 if successful 42* 43* @implemented 44*/ 45INT_PTR 46WINAPI 47DeviceAdvancedPropertiesW(IN HWND hWndParent OPTIONAL, 48 IN LPCWSTR lpMachineName OPTIONAL, 49 IN LPCWSTR lpDeviceID) 50{ 51 HDEVINFO hDevInfo; 52 SP_DEVINFO_DATA DevInfoData; 53 HINSTANCE hComCtl32; 54 INT_PTR Ret = -1; 55 56 if (lpDeviceID == NULL) 57 { 58 SetLastError(ERROR_INVALID_PARAMETER); 59 return FALSE; 60 } 61 62 /* dynamically load comctl32 */ 63 hComCtl32 = LoadAndInitComctl32(); 64 if (hComCtl32 != NULL) 65 { 66 hDevInfo = SetupDiCreateDeviceInfoListEx(NULL, 67 hWndParent, 68 lpMachineName, 69 NULL); 70 if (hDevInfo != INVALID_HANDLE_VALUE) 71 { 72 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 73 if (SetupDiOpenDeviceInfo(hDevInfo, 74 lpDeviceID, 75 hWndParent, 76 0, 77 &DevInfoData)) 78 { 79 Ret = DisplayDeviceAdvancedProperties(hWndParent, 80 lpDeviceID, 81 hDevInfo, 82 &DevInfoData, 83 hComCtl32, 84 lpMachineName, 85 0); 86 } 87 88 SetupDiDestroyDeviceInfoList(hDevInfo); 89 } 90 91 FreeLibrary(hComCtl32); 92 } 93 94 return Ret; 95} 96 97 98/*************************************************************************** 99* NAME EXPORTED 100* DeviceAdvancedPropertiesA 101* 102* DESCRIPTION 103* Invokes the device properties dialog, this version may add some property pages 104* for some devices 105* 106* ARGUMENTS 107* hWndParent: Handle to the parent window 108* lpMachineName: Machine Name, NULL is the local machine 109* lpDeviceID: Specifies the device whose properties are to be shown 110* 111* RETURN VALUE 112* Always returns -1, a call to GetLastError returns 0 if successful 113* 114* @implemented 115*/ 116INT_PTR 117WINAPI 118DeviceAdvancedPropertiesA(IN HWND hWndParent OPTIONAL, 119 IN LPCSTR lpMachineName OPTIONAL, 120 IN LPCSTR lpDeviceID) 121{ 122 LPWSTR lpMachineNameW = NULL; 123 LPWSTR lpDeviceIDW = NULL; 124 INT_PTR Ret = -1; 125 126 if (lpMachineName != NULL) 127 { 128 if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName, 129 CP_ACP))) 130 { 131 goto Cleanup; 132 } 133 } 134 if (lpDeviceID != NULL) 135 { 136 if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID, 137 CP_ACP))) 138 { 139 goto Cleanup; 140 } 141 } 142 143 Ret = DeviceAdvancedPropertiesW(hWndParent, 144 lpMachineNameW, 145 lpDeviceIDW); 146 147Cleanup: 148 if (lpMachineNameW != NULL) 149 { 150 HeapFree(GetProcessHeap(), 151 0, 152 lpMachineNameW); 153 } 154 if (lpDeviceIDW != NULL) 155 { 156 HeapFree(GetProcessHeap(), 157 0, 158 lpDeviceIDW); 159 } 160 161 return Ret; 162} 163 164 165/*************************************************************************** 166* NAME EXPORTED 167* DevicePropertiesExA 168* 169* DESCRIPTION 170* Invokes the extended device properties dialog 171* 172* ARGUMENTS 173* hWndParent: Handle to the parent window 174* lpMachineName: Machine Name, NULL is the local machine 175* lpDeviceID: Specifies the device whose properties are to be shown, optional if 176* bShowDevMgr is nonzero 177* dwFlags: This parameter can be a combination of the following flags: 178* * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes 179* the default device status action button 180* to be clicked (Troubleshoot, Enable 181* Device, etc) 182* bShowDevMgr: If non-zero it displays the device manager instead of 183* the advanced device property dialog 184* 185* RETURN VALUE 186* 1: if bShowDevMgr is non-zero and no error occured 187* -1: a call to GetLastError returns 0 if successful 188* 189* @implemented 190*/ 191INT_PTR 192WINAPI 193DevicePropertiesExA(IN HWND hWndParent OPTIONAL, 194 IN LPCSTR lpMachineName OPTIONAL, 195 IN LPCSTR lpDeviceID OPTIONAL, 196 IN DWORD dwFlags OPTIONAL, 197 IN BOOL bShowDevMgr) 198{ 199 LPWSTR lpMachineNameW = NULL; 200 LPWSTR lpDeviceIDW = NULL; 201 INT_PTR Ret = -1; 202 203 if (lpMachineName != NULL) 204 { 205 if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName, 206 CP_ACP))) 207 { 208 goto Cleanup; 209 } 210 } 211 if (lpDeviceID != NULL) 212 { 213 if (!(lpDeviceIDW = ConvertMultiByteToUnicode(lpDeviceID, 214 CP_ACP))) 215 { 216 goto Cleanup; 217 } 218 } 219 220 Ret = DevicePropertiesExW(hWndParent, 221 lpMachineNameW, 222 lpDeviceIDW, 223 dwFlags, 224 bShowDevMgr); 225 226Cleanup: 227 if (lpMachineNameW != NULL) 228 { 229 HeapFree(GetProcessHeap(), 230 0, 231 lpMachineNameW); 232 } 233 if (lpDeviceIDW != NULL) 234 { 235 HeapFree(GetProcessHeap(), 236 0, 237 lpDeviceIDW); 238 } 239 240 return Ret; 241} 242 243 244/*************************************************************************** 245* NAME EXPORTED 246* DevicePropertiesExW 247* 248* DESCRIPTION 249* Invokes the extended device properties dialog 250* 251* ARGUMENTS 252* hWndParent: Handle to the parent window 253* lpMachineName: Machine Name, NULL is the local machine 254* lpDeviceID: Specifies the device whose properties are to be shown, optional if 255* bShowDevMgr is nonzero 256* dwFlags: This parameter can be a combination of the following flags: 257* * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes 258* the default device status action button 259* to be clicked (Troubleshoot, Enable 260* Device, etc) 261* bShowDevMgr: If non-zero it displays the device manager instead of 262* the advanced device property dialog 263* 264* RETURN VALUE 265* 1: if bShowDevMgr is non-zero and no error occured 266* -1: a call to GetLastError returns 0 if successful 267* 268* @implemented 269*/ 270INT_PTR 271WINAPI 272DevicePropertiesExW(IN HWND hWndParent OPTIONAL, 273 IN LPCWSTR lpMachineName OPTIONAL, 274 IN LPCWSTR lpDeviceID OPTIONAL, 275 IN DWORD dwFlags OPTIONAL, 276 IN BOOL bShowDevMgr) 277{ 278 INT_PTR Ret = -1; 279 280 if (dwFlags & ~(DPF_EXTENDED | DPF_DEVICE_STATUS_ACTION)) 281 { 282 FIXME("DevPropertiesExW: Invalid flags: 0x%x\n", 283 dwFlags & ~(DPF_EXTENDED | DPF_DEVICE_STATUS_ACTION)); 284 SetLastError(ERROR_INVALID_FLAGS); 285 return -1; 286 } 287 288 if (bShowDevMgr) 289 { 290 FIXME("DevPropertiesExW doesn't support bShowDevMgr!\n"); 291 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 292 } 293 else 294 { 295 HDEVINFO hDevInfo; 296 SP_DEVINFO_DATA DevInfoData; 297 HINSTANCE hComCtl32; 298 299 if (lpDeviceID == NULL) 300 { 301 SetLastError(ERROR_INVALID_PARAMETER); 302 return -1; 303 } 304 305 /* dynamically load comctl32 */ 306 hComCtl32 = LoadAndInitComctl32(); 307 if (hComCtl32 != NULL) 308 { 309 hDevInfo = SetupDiCreateDeviceInfoListEx(NULL, 310 hWndParent, 311 lpMachineName, 312 NULL); 313 if (hDevInfo != INVALID_HANDLE_VALUE) 314 { 315 DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); 316 if (SetupDiOpenDeviceInfo(hDevInfo, 317 lpDeviceID, 318 hWndParent, 319 0, 320 &DevInfoData)) 321 { 322 Ret = DisplayDeviceAdvancedProperties(hWndParent, 323 lpDeviceID, 324 hDevInfo, 325 &DevInfoData, 326 hComCtl32, 327 lpMachineName, 328 dwFlags); 329 } 330 331 SetupDiDestroyDeviceInfoList(hDevInfo); 332 } 333 334 FreeLibrary(hComCtl32); 335 } 336 } 337 338 return Ret; 339} 340 341 342/*************************************************************************** 343* NAME EXPORTED 344* DevicePropertiesA 345* 346* DESCRIPTION 347* Invokes the device properties dialog directly 348* 349* ARGUMENTS 350* hWndParent: Handle to the parent window 351* lpMachineName: Machine Name, NULL is the local machine 352* lpDeviceID: Specifies the device whose properties are to be shown 353* bShowDevMgr: If non-zero it displays the device manager instead of 354* the device property dialog 355* 356* RETURN VALUE 357* >=0: if no errors occured 358* -1: if errors occured 359* 360* REVISIONS 361* 362* @implemented 363*/ 364int 365WINAPI 366DevicePropertiesA(HWND hWndParent, 367 LPCSTR lpMachineName, 368 LPCSTR lpDeviceID, 369 BOOL bShowDevMgr) 370{ 371 return DevicePropertiesExA(hWndParent, 372 lpMachineName, 373 lpDeviceID, 374 DPF_EXTENDED, 375 bShowDevMgr); 376} 377 378 379/*************************************************************************** 380* NAME EXPORTED 381* DevicePropertiesW 382* 383* DESCRIPTION 384* Invokes the device properties dialog directly 385* 386* ARGUMENTS 387* hWndParent: Handle to the parent window 388* lpMachineName: Machine Name, NULL is the local machine 389* lpDeviceID: Specifies the device whose properties are to be shown 390* bShowDevMgr: If non-zero it displays the device manager instead of 391* the device property dialog 392* 393* RETURN VALUE 394* >=0: if no errors occured 395* -1: if errors occured 396* 397* REVISIONS 398* 399* @implemented 400*/ 401int 402WINAPI 403DevicePropertiesW(HWND hWndParent, 404 LPCWSTR lpMachineName, 405 LPCWSTR lpDeviceID, 406 BOOL bShowDevMgr) 407{ 408 return DevicePropertiesExW(hWndParent, 409 lpMachineName, 410 lpDeviceID, 411 DPF_EXTENDED, 412 bShowDevMgr); 413} 414 415 416/*************************************************************************** 417* NAME EXPORTED 418* DeviceProperties_RunDLLA 419* 420* DESCRIPTION 421* Invokes the device properties dialog 422* 423* ARGUMENTS 424* hWndParent: Handle to the parent window 425* hInst: Handle to the application instance 426* lpDeviceCmd: A command that includes the DeviceID of the properties to be shown, 427* also see NOTEs 428* nCmdShow: Specifies how the window should be shown 429* 430* RETURN VALUE 431* 432* REVISIONS 433* 434* NOTE 435* - lpDeviceCmd is a string in the form of "/MachineName MACHINE /DeviceID DEVICEPATH" 436* (/MachineName is optional). This function only parses this string and eventually 437* calls DeviceProperties(). 438* 439* @implemented 440*/ 441VOID 442WINAPI 443DeviceProperties_RunDLLA(HWND hWndParent, 444 HINSTANCE hInst, 445 LPCSTR lpDeviceCmd, 446 int nCmdShow) 447{ 448 LPWSTR lpDeviceCmdW = NULL; 449 450 if (lpDeviceCmd != NULL) 451 { 452 if ((lpDeviceCmdW = ConvertMultiByteToUnicode(lpDeviceCmd, 453 CP_ACP))) 454 { 455 DeviceProperties_RunDLLW(hWndParent, 456 hInst, 457 lpDeviceCmdW, 458 nCmdShow); 459 } 460 } 461 462 if (lpDeviceCmdW != NULL) 463 { 464 HeapFree(GetProcessHeap(), 465 0, 466 lpDeviceCmdW); 467 } 468} 469 470 471/*************************************************************************** 472* NAME EXPORTED 473* DeviceProperties_RunDLLW 474* 475* DESCRIPTION 476* Invokes the device properties dialog 477* 478* ARGUMENTS 479* hWndParent: Handle to the parent window 480* hInst: Handle to the application instance 481* lpDeviceCmd: A command that includes the DeviceID of the properties to be shown, 482* also see NOTEs 483* nCmdShow: Specifies how the window should be shown 484* 485* RETURN VALUE 486* 487* REVISIONS 488* 489* NOTE 490* - lpDeviceCmd is a string in the form of "/MachineName MACHINE /DeviceID DEVICEPATH" 491* (/MachineName is optional). This function only parses this string and eventually 492* calls DeviceProperties(). 493* 494* @implemented 495*/ 496VOID 497WINAPI 498DeviceProperties_RunDLLW(HWND hWndParent, 499 HINSTANCE hInst, 500 LPCWSTR lpDeviceCmd, 501 int nCmdShow) 502{ 503 WCHAR szDeviceID[MAX_DEVICE_ID_LEN + 1]; 504 WCHAR szMachineName[MAX_COMPUTERNAME_LENGTH + 1]; 505 LPWSTR lpString = (LPWSTR)lpDeviceCmd; 506 507 if (!GetDeviceAndComputerName(lpString, 508 szDeviceID, 509 szMachineName)) 510 { 511 ERR("DeviceProperties_RunDLLW DeviceID: %S, MachineName: %S\n", szDeviceID, szMachineName); 512 return; 513 } 514 515 DevicePropertiesW(hWndParent, 516 szMachineName, 517 szDeviceID, 518 FALSE); 519} 520 521 522 523/*************************************************************************** 524* NAME EXPORTED 525* DeviceManager_ExecuteA 526* 527* DESCRIPTION 528* Starts the Device Manager 529* 530* ARGUMENTS 531* hWndParent: Handle to the parent window 532* hInst: Handle to the application instance 533* lpMachineName: Machine Name, NULL is the local machine 534* nCmdShow: Specifies how the window should be shown 535* 536* RETURN VALUE 537* TRUE: if no errors occured 538* FALSE: if the device manager could not be executed 539* 540* REVISIONS 541* 542* NOTE 543* - Win runs the device manager in a separate process, so hWndParent is somehow 544* obsolete. 545* 546* @implemented 547*/ 548BOOL 549WINAPI 550DeviceManager_ExecuteA(HWND hWndParent, 551 HINSTANCE hInst, 552 LPCSTR lpMachineName, 553 int nCmdShow) 554{ 555 LPWSTR lpMachineNameW = NULL; 556 BOOL Ret; 557 558 if (lpMachineName != NULL) 559 { 560 if (!(lpMachineNameW = ConvertMultiByteToUnicode(lpMachineName, 561 CP_ACP))) 562 { 563 return FALSE; 564 } 565 } 566 567 Ret = DeviceManager_ExecuteW(hWndParent, 568 hInst, 569 lpMachineNameW, 570 nCmdShow); 571 572 if (lpMachineNameW != NULL) 573 { 574 HeapFree(GetProcessHeap(), 575 0, 576 lpMachineNameW); 577 } 578 579 580 return Ret; 581} 582 583 584/*************************************************************************** 585* NAME EXPORTED 586* DeviceManager_ExecuteW 587* 588* DESCRIPTION 589* Starts the Device Manager 590* 591* ARGUMENTS 592* hWndParent: Handle to the parent window 593* hInst: Handle to the application instance 594* lpMachineName: Machine Name, NULL is the local machine 595* nCmdShow: Specifies how the window should be shown 596* 597* RETURN VALUE 598* TRUE: if no errors occured 599* FALSE: if the device manager could not be executed 600* 601* REVISIONS 602* 603* NOTE 604* - Win runs the device manager in a separate process, so hWndParent is somehow 605* obsolete. 606* 607* @implemented 608*/ 609BOOL 610WINAPI 611DeviceManager_ExecuteW(HWND hWndParent, 612 HINSTANCE hInst, 613 LPCWSTR lpMachineName, 614 int nCmdShow) 615{ 616 // FIXME: Call mmc with devmgmt.msc 617 618 CDeviceManager DevMgr; 619 return DevMgr.Create(hWndParent, hInst, lpMachineName, nCmdShow); 620} 621 622 623/*************************************************************************** 624* NAME EXPORTED 625* DeviceProblemWizard_RunDLLA 626* 627* DESCRIPTION 628* Calls the device problem wizard 629* 630* ARGUMENTS 631* hWndParent: Handle to the parent window 632* hInst: Handle to the application instance 633* lpDeviceCmd: A command that includes the DeviceID of the properties to be shown, 634* also see NOTEs 635* nCmdShow: Specifies how the window should be shown 636* 637* RETURN VALUE 638* 639* REVISIONS 640* 641* NOTE 642* - Win XP exports this function as DeviceProblenWizard_RunDLLA, apparently it's 643* a typo so we additionally export an alias function 644* - lpDeviceCmd is a string in the form of "/MachineName MACHINE /DeviceID DEVICEPATH" 645* (/MachineName is optional). This function only parses this string and eventually 646* calls DeviceProperties(). 647* 648* @unimplemented 649*/ 650VOID 651WINAPI 652DeviceProblemWizard_RunDLLA(HWND hWndParent, 653 HINSTANCE hInst, 654 LPCSTR lpDeviceCmd, 655 int nCmdShow) 656{ 657 UNIMPLEMENTED; 658} 659 660 661/*************************************************************************** 662* NAME EXPORTED 663* DeviceProblemWizard_RunDLLW 664* 665* DESCRIPTION 666* Calls the device problem wizard 667* 668* ARGUMENTS 669* hWndParent: Handle to the parent window 670* hInst: Handle to the application instance 671* lpDeviceCmd: A command that includes the DeviceID of the properties to be shown, 672* also see NOTEs 673* nCmdShow: Specifies how the window should be shown 674* 675* RETURN VALUE 676* 677* REVISIONS 678* 679* NOTE 680* - Win XP exports this function as DeviceProblenWizard_RunDLLA, apparently it's 681* a typo so we additionally export an alias function 682* - lpDeviceCmd is a string in the form of "/MachineName MACHINE /DeviceID DEVICEPATH" 683* (/MachineName is optional). This function only parses this string and eventually 684* calls DeviceProperties(). 685* 686* @unimplemented 687*/ 688VOID 689WINAPI 690DeviceProblemWizard_RunDLLW(HWND hWndParent, 691 HINSTANCE hInst, 692 LPCWSTR lpDeviceCmd, 693 int nCmdShow) 694{ 695 UNIMPLEMENTED; 696} 697 698 699/*************************************************************************** 700* NAME EXPORTED 701* DeviceManagerPrintA 702* 703* DESCRIPTION 704* Calls the device problem wizard 705* 706* ARGUMENTS 707* lpMachineName: Machine Name, NULL is the local machine 708* lpPrinter: Filename of the printer where it should be printed on 709* nPrintMode: Specifies what kind of information is to be printed 710* DEV_PRINT_ABSTRACT: Prints an abstract of system information, the parameters 711* uNumberOfGuids, Guids are ignored 712* DEV_PRINT_SELECTED: Prints information about the devices listed in Guids 713* DEV_PRINT_ALL: Prints an abstract of system information and all 714* system devices 715* uNumberOfGuids: Numbers of guids in the Guids array, this parameter is ignored unless 716* nPrintMode is DEV_PRINT_SELECTED 717* lpGuids: Array of device guids, this parameter is ignored unless 718* nPrintMode is DEV_PRINT_SELECTED 719* 720* RETURN VALUE 721* TRUE: if no errors occured 722* FALSE: if errors occured 723* 724* REVISIONS 725* 726* NOTE 727* 728* @unimplemented 729*/ 730BOOL 731WINAPI 732DeviceManagerPrintA(LPCSTR lpMachineName, 733 LPCSTR lpPrinter, 734 int nPrintMode, 735 UINT uNumberOfGuids, 736 LPGUID lpGuids) 737{ 738 UNIMPLEMENTED; 739 return FALSE; 740} 741 742 743/*************************************************************************** 744* NAME EXPORTED 745* DeviceManagerPrintW 746* 747* DESCRIPTION 748* Calls the device problem wizard 749* 750* ARGUMENTS 751* lpMachineName: Machine Name, NULL is the local machine 752* lpPrinter: Filename of the printer where it should be printed on 753* nPrintMode: Specifies what kind of information is to be printed 754* DEV_PRINT_ABSTRACT: Prints an abstract of system information, the parameters 755* uNumberOfGuids, Guids are ignored 756* DEV_PRINT_SELECTED: Prints information about the devices listed in Guids 757* DEV_PRINT_ALL: Prints an abstract of system information and all 758* system devices 759* uNumberOfGuids: Numbers of guids in the Guids array, this parameter is ignored unless 760* nPrintMode is DEV_PRINT_SELECTED 761* lpGuids: Array of device guids, this parameter is ignored unless 762* nPrintMode is DEV_PRINT_SELECTED 763* 764* RETURN VALUE 765* TRUE: if no errors occured 766* FALSE: if errors occured 767* 768* REVISIONS 769* 770* NOTE 771* 772* @unimplemented 773*/ 774BOOL 775WINAPI 776DeviceManagerPrintW(LPCWSTR lpMachineName, 777 LPCWSTR lpPrinter, 778 int nPrintMode, 779 UINT uNumberOfGuids, 780 LPGUID lpGuids) 781{ 782 UNIMPLEMENTED; 783 return FALSE; 784} 785 786class CDevMgrUIModule : public CComModule 787{ 788public: 789}; 790 791CDevMgrUIModule gModule; 792 793STDAPI DllCanUnloadNow() 794{ 795 return gModule.DllCanUnloadNow(); 796} 797 798STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) 799{ 800 return gModule.DllGetClassObject(rclsid, riid, ppv); 801} 802 803STDAPI DllRegisterServer() 804{ 805 return gModule.DllRegisterServer(FALSE); 806} 807 808STDAPI DllUnregisterServer() 809{ 810 return gModule.DllUnregisterServer(FALSE); 811} 812 813extern "C" { 814 815BOOL 816WINAPI 817DllMain(_In_ HINSTANCE hinstDLL, 818 _In_ DWORD dwReason, 819 _In_ LPVOID lpvReserved) 820{ 821 switch (dwReason) 822 { 823 case DLL_PROCESS_ATTACH: 824 DisableThreadLibraryCalls(hinstDLL); 825 hDllInstance = hinstDLL; 826 break; 827 } 828 829 return TRUE; 830} 831}