|
|
1.1 ! root 1: /**************************************************************************** ! 2: * ! 3: * registry.c ! 4: * ! 5: * Copyright (c) 1992 Microsoft Corporation. All Rights Reserved. ! 6: * ! 7: * This file contains functions to maintain registry entries for ! 8: * kernel drivers installed via the drivers control panel applet. ! 9: * ! 10: * Note that the ONLY state maintained between calls here is whatever ! 11: * state the registry and its handles maintain. ! 12: * ! 13: * The registry entries are structured as follows : ! 14: * (see also winreg.h, winnt.h) ! 15: * ! 16: * HKEY_LOCAL_MACHINE ! 17: * SYSTEM ! 18: * CurrentControlSet ! 19: * Services ! 20: * DriverNode (eg sndblst) ! 21: * Type = SERVICE_KERNEL_DRIVER (eg) ! 22: * Group = "Base" ! 23: * ErrorControl = SERVICE_ERROR_NORMAL ! 24: * Start = SERVICE_SYSTEM_START | ! 25: * SERVICE_DEMAND_START | ! 26: * SERVICE_DISABLED ! 27: * ... ! 28: * Tag = A unique number ??? ! 29: * ! 30: * Device ! 31: * Interrupt = ! 32: * Port = ! 33: * DMAChannel = ! 34: * ! 35: * The Driver node is set up by the services manager when we call ! 36: * CreateService but we have to insert the device data ourselves. ! 37: * ! 38: * ! 39: * ! 40: * The registry entries are shared between : ! 41: * ! 42: * The system loader (which uses the Services entry) ! 43: * The kernel driver (which reads from the Device entry) ! 44: * This component called from the drivers control panel applet ! 45: * The service control manager ! 46: * The Setup utility ! 47: * ! 48: * Security access ! 49: * --------------- ! 50: * ! 51: * The driver determines whether it can perform configuration and ! 52: * installation by whether it can get read and write access to the ! 53: * service control manager. This is required to manipulate the kernel ! 54: * driver database. ! 55: * ! 56: * Services controller ! 57: * ------------------- ! 58: * ! 59: * The services controller is used because this is the only way we ! 60: * are allowed to load and unload kernel drivers. Only the services ! 61: * controller can call LoadDriver and UnloadDriver and not get 'access ! 62: * denied'. ! 63: * ! 64: * Note also that we can't keep the services controller handle open ! 65: * at the same time as the registry handle because then we can't get ! 66: * write access (actually we only need KEY_CREATE_SUB_KEY access) to ! 67: * our device parameters subkey. ! 68: * ! 69: ***************************************************************************/ ! 70: ! 71: #include <stdio.h> ! 72: #ifdef UNICODE ! 73: #include <wchar.h> ! 74: #else ! 75: #include <string.h> ! 76: #define wcscat strcat ! 77: #define wcscpy strcpy ! 78: #define wcsicmp stricmp ! 79: #endif ! 80: #include <windows.h> ! 81: #include <mmsystem.h> ! 82: #include <winsvc.h> ! 83: #include <soundcfg.h> ! 84: #include "registry.h" ! 85: ! 86: /*************************************************************************** ! 87: * ! 88: * Constants for accessing the registry ! 89: * ! 90: ***************************************************************************/ ! 91: ! 92: /* ! 93: * Path to service node key ! 94: */ ! 95: ! 96: #define STR_SERVICES_NODE TEXT("SYSTEM\\CurrentControlSet\\Services\\") ! 97: ! 98: /* ! 99: * Node sub-key for device parameters ! 100: */ ! 101: ! 102: #define STR_DEVICE_DATA PARMS_SUBKEY ! 103: ! 104: /* ! 105: * Name of Base group where sound drivers normally go ! 106: */ ! 107: ! 108: #define STR_BASE_GROUP TEXT("Base") ! 109: ! 110: /* ! 111: * Name of driver group for synthesizers ! 112: * - we use our own name here to make sure ! 113: * we are loaded after things like the PAS driver. (Base is a ! 114: * known group and drivers in it are always loaded before unknown ! 115: * groups like this one). ! 116: */ ! 117: ! 118: #define STR_SYNTH_GROUP TEXT("Synthesizer Drivers") ! 119: ! 120: /* ! 121: * Name of service ! 122: */ ! 123: ! 124: #define STR_DRIVER TEXT("\\Driver\\") ! 125: ! 126: /* ! 127: * Path to kernel drivers directory from system directory ! 128: */ ! 129: ! 130: #define STR_DRIVERS_DIR TEXT("\\SystemRoot\\SYSTEM32\\DRIVERS\\") ! 131: ! 132: /* ! 133: * Extension for drivers ! 134: */ ! 135: ! 136: #define STR_SYS_EXT TEXT(".SYS") ! 137: ! 138: ! 139: HKEY DrvOpenRegKey(LPTSTR DriverName) ! 140: { ! 141: TCHAR RegistryPath[MAX_PATH]; ! 142: HKEY NodeHandle; ! 143: ! 144: // ! 145: // Create the path to our node ! 146: // ! 147: ! 148: wcscpy(RegistryPath, STR_SERVICES_NODE); ! 149: wcscat(RegistryPath, DriverName); ! 150: ! 151: // ! 152: // See if we can get a registry handle to our device data ! 153: // ! 154: ! 155: ! 156: if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, ! 157: RegistryPath, ! 158: 0L, ! 159: KEY_ALL_ACCESS, ! 160: &NodeHandle) ! 161: != ERROR_SUCCESS) { ! 162: return NULL; ! 163: } else { ! 164: return NodeHandle; ! 165: } ! 166: } ! 167: ! 168: ! 169: SC_HANDLE DrvOpenService(PREG_ACCESS RegAccess) ! 170: { ! 171: SC_HANDLE Handle; ! 172: Handle = OpenService(RegAccess->ServiceManagerHandle, ! 173: RegAccess->DriverName, ! 174: SERVICE_ALL_ACCESS); ! 175: ! 176: #if 0 ! 177: if (Handle == NULL) { ! 178: char buf[100]; ! 179: sprintf(buf, "OpenService failed code %d\n", GetLastError()); ! 180: OutputDebugStringA(buf); ! 181: } ! 182: #endif ! 183: ! 184: return Handle; ! 185: } ! 186: ! 187: void DrvCloseService(PREG_ACCESS RegAccess, SC_HANDLE ServiceHandle) ! 188: { ! 189: CloseServiceHandle(ServiceHandle); ! 190: } ! 191: ! 192: /*************************************************************************** ! 193: * ! 194: * Function : ! 195: * DrvCreateServicesNode ! 196: * ! 197: * Parameters : ! 198: * DriverNodeName The name of the service node. Same as the ! 199: * name of the driver which must be ! 200: * DriverNodeName.sys for the system to find it. ! 201: * ! 202: * DriverType Type of driver - see registry.h ! 203: * ! 204: * ServiceNodeKey Pointer to where to put returned handle ! 205: * ! 206: * Return code : ! 207: * ! 208: * Standard error code (see winerror.h) ! 209: * ! 210: * Description : ! 211: * ! 212: * Create the service node key ! 213: * ! 214: * The class name of the registry node is "" ! 215: * ! 216: ***************************************************************************/ ! 217: ! 218: BOOL ! 219: DrvCreateServicesNode(LPTSTR DriverName, ! 220: SOUND_KERNEL_MODE_DRIVER_TYPE DriverType, ! 221: PREG_ACCESS RegAccess, ! 222: BOOL Create) ! 223: { ! 224: SERVICE_STATUS ServiceStatus; ! 225: SC_HANDLE ServiceHandle; // Handle to our driver 'service' ! 226: ! 227: RegAccess->DriverName = DriverName; ! 228: ! 229: // ! 230: // See if we can open the registry ! 231: // ! 232: ! 233: if (RegAccess->ServiceManagerHandle == NULL) { ! 234: RegAccess->ServiceManagerHandle = ! 235: OpenSCManager( ! 236: NULL, // This machine ! 237: NULL, // The active database ! 238: SC_MANAGER_ALL_ACCESS); // We want to create and change ! 239: ! 240: if (RegAccess->ServiceManagerHandle == NULL) { ! 241: return FALSE; ! 242: } ! 243: } ! 244: ! 245: // ! 246: // Open our particular service ! 247: // ! 248: ! 249: ServiceHandle = DrvOpenService(RegAccess); ! 250: ! 251: // ! 252: // See if that worked ! 253: // ! 254: ! 255: if (ServiceHandle == NULL && ! 256: GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST) { ! 257: if (Create) { ! 258: SC_LOCK ServicesDatabaseLock; ! 259: TCHAR ServiceName[MAX_PATH]; ! 260: TCHAR BinaryPath[MAX_PATH]; ! 261: ! 262: wcscpy(BinaryPath, STR_DRIVERS_DIR); ! 263: wcscat(BinaryPath, DriverName); ! 264: wcscat(BinaryPath, STR_SYS_EXT); ! 265: ! 266: wcscpy(ServiceName, STR_DRIVER); ! 267: wcscat(ServiceName, DriverName); ! 268: ! 269: /* ! 270: * Lock the service controller database to avoid deadlocks ! 271: * we have to loop because we can't wait ! 272: */ ! 273: ! 274: ! 275: for (ServicesDatabaseLock = NULL; ! 276: (ServicesDatabaseLock = ! 277: LockServiceDatabase(RegAccess->ServiceManagerHandle)) ! 278: == NULL; ! 279: Sleep(100)) { ! 280: } ! 281: ! 282: ! 283: /* ! 284: * Create the service ! 285: */ ! 286: ! 287: ! 288: ServiceHandle = ! 289: CreateService( ! 290: RegAccess->ServiceManagerHandle, ! 291: DriverName, // Service name ! 292: NULL, // ??? ! 293: SERVICE_ALL_ACCESS, // Full access ! 294: SERVICE_KERNEL_DRIVER, // Kernel driver ! 295: SERVICE_DEMAND_START, // Start at sys start ! 296: SERVICE_ERROR_NORMAL, // Not a disaster if fails ! 297: BinaryPath, // Default path ! 298: ! 299: DriverType == SoundDriverTypeSynth ? ! 300: STR_SYNTH_GROUP : // Driver group ! 301: STR_BASE_GROUP, ! 302: NULL, // do not want TAG information ! 303: TEXT("\0"), // No dependencies ! 304: NULL, // ServiceName, // Driver object - optional ! 305: NULL); // No password ! 306: ! 307: UnlockServiceDatabase(ServicesDatabaseLock); ! 308: #if DBG ! 309: if (ServiceHandle == NULL) { ! 310: TCHAR buf[100]; ! 311: wsprintf(buf, TEXT("CreateService failed code %d\n"), GetLastError()); ! 312: OutputDebugString(buf); ! 313: } ! 314: #endif ! 315: ! 316: } ! 317: } ! 318: ! 319: // ! 320: // Check at least that it's a device driver ! 321: // ! 322: ! 323: if (ServiceHandle != NULL) { ! 324: if (!QueryServiceStatus( ! 325: ServiceHandle, ! 326: &ServiceStatus) || ! 327: ServiceStatus.dwServiceType != SERVICE_KERNEL_DRIVER) { ! 328: ! 329: // ! 330: // Doesn't look like ours ! 331: // ! 332: ! 333: CloseServiceHandle(RegAccess->ServiceManagerHandle); ! 334: RegAccess->ServiceManagerHandle = NULL; ! 335: DrvCloseService(RegAccess, ServiceHandle); ! 336: return FALSE; ! 337: } ! 338: ! 339: } ! 340: ! 341: if (ServiceHandle == NULL) { ! 342: // ! 343: // Leave the SC manager handle open. We use the presence of this ! 344: // handle to test whether the driver can be configured (ie whether we ! 345: // have the access rights to get into the SC manager). ! 346: // ! 347: ! 348: return FALSE; ! 349: } else { ! 350: // ! 351: // We can't keep this handle open (even though we'd like to) because ! 352: // we need write access to the registry node created so that ! 353: // we can add device parameters ! 354: // ! 355: ! 356: DrvCloseService(RegAccess, ServiceHandle); ! 357: return TRUE; ! 358: } ! 359: } ! 360: ! 361: ! 362: /*************************************************************************** ! 363: * ! 364: * Function : ! 365: * DrvCloseServicesNode ! 366: * ! 367: * Parameters : ! 368: * ServiceNodeKey ! 369: * ! 370: * Return code : ! 371: * ! 372: * Standard error code (see winerror.h) ! 373: * ! 374: * Description : ! 375: * ! 376: * Close our handle ! 377: * ! 378: ***************************************************************************/ ! 379: ! 380: VOID ! 381: DrvCloseServiceManager( ! 382: PREG_ACCESS RegAccess) ! 383: { ! 384: if (RegAccess->ServiceManagerHandle != NULL) { ! 385: CloseServiceHandle(RegAccess->ServiceManagerHandle); ! 386: RegAccess->ServiceManagerHandle = NULL; ! 387: } ! 388: } ! 389: ! 390: /*************************************************************************** ! 391: * ! 392: * Function : ! 393: * DrvDeleteServicesNode ! 394: * ! 395: * Parameters : ! 396: * DeviceName ! 397: * ! 398: * Return code : ! 399: * ! 400: * TRUE = success, FALSE = failed ! 401: * ! 402: * Description : ! 403: * ! 404: * Delete our node using the handle proviced ! 405: * ! 406: ***************************************************************************/ ! 407: ! 408: BOOL ! 409: DrvDeleteServicesNode( ! 410: PREG_ACCESS RegAccess) ! 411: { ! 412: BOOL Success; ! 413: SC_LOCK ServicesDatabaseLock; ! 414: SC_HANDLE ServiceHandle; ! 415: HKEY NodeHandle; ! 416: ! 417: NodeHandle = DrvOpenRegKey(RegAccess->DriverName); ! 418: ! 419: // ! 420: // Make sure we're not accessing the registry ourselves and ! 421: // that there aren't any subkeys ! 422: // ! 423: ! 424: if (NodeHandle) { ! 425: RegDeleteKey(NodeHandle, STR_DEVICE_DATA); ! 426: RegFlushKey(NodeHandle); ! 427: RegCloseKey(NodeHandle); ! 428: } ! 429: ! 430: // ! 431: // Delete the service node and free tha handle ! 432: // (Note the service cannot be deleted until all handles are closed) ! 433: // ! 434: ! 435: ServiceHandle = DrvOpenService(RegAccess); ! 436: ! 437: if (ServiceHandle == NULL) { ! 438: LONG Error; ! 439: Error = GetLastError(); ! 440: if (Error == ERROR_SERVICE_DOES_NOT_EXIST) { ! 441: // ! 442: // It's already gone ! ! 443: // ! 444: return TRUE; ! 445: } else { ! 446: return FALSE; // It was there but something went wrong ! 447: } ! 448: } ! 449: ! 450: /* ! 451: * Lock the service controller database to avoid deadlocks ! 452: * we have to loop because we can't wait ! 453: */ ! 454: ! 455: ! 456: for (ServicesDatabaseLock = NULL; ! 457: (ServicesDatabaseLock = ! 458: LockServiceDatabase(RegAccess->ServiceManagerHandle)) ! 459: == NULL; ! 460: Sleep(100)) { ! 461: } ! 462: ! 463: Success = DeleteService(ServiceHandle); ! 464: ! 465: UnlockServiceDatabase(ServicesDatabaseLock); ! 466: ! 467: DrvCloseService(RegAccess, ServiceHandle); ! 468: ! 469: return Success; ! 470: } ! 471: ! 472: ! 473: /*************************************************************************** ! 474: * ! 475: * Function : ! 476: * DrvSetDeviceParameter ! 477: * ! 478: * Parameters : ! 479: * ServiceNodeKey Handle to the device services node key ! 480: * ValueName Name of value to set ! 481: * Value DWORD value to set ! 482: * ! 483: * Return code : ! 484: * ! 485: * Standard error code (see winerror.h) ! 486: * ! 487: * Description : ! 488: * ! 489: * Add the value to the device parameters section under the ! 490: * services node. ! 491: * This section is created if it does not already exist. ! 492: * ! 493: ***************************************************************************/ ! 494: ! 495: LONG ! 496: DrvSetDeviceParameter( ! 497: PREG_ACCESS RegAccess, ! 498: LPTSTR ValueName, ! 499: DWORD Value) ! 500: { ! 501: HKEY ServiceNodeKey; ! 502: HKEY ParmsKey; ! 503: LONG ReturnCode; ! 504: ! 505: ServiceNodeKey = DrvOpenRegKey(RegAccess->DriverName); ! 506: ! 507: if (ServiceNodeKey == NULL) { ! 508: return ERROR_FILE_NOT_FOUND; ! 509: } ! 510: ! 511: // ! 512: // First try to get a handle to the parameters subkey - which may ! 513: // involve creating the subkey ! 514: // ! 515: ! 516: ReturnCode = RegCreateKey(ServiceNodeKey, STR_DEVICE_DATA, &ParmsKey); ! 517: ! 518: RegCloseKey(ServiceNodeKey); ! 519: ! 520: if (ReturnCode != ERROR_SUCCESS) { ! 521: return ReturnCode; ! 522: } ! 523: ! 524: // ! 525: // Write the value ! 526: // ! 527: ! 528: ! 529: ReturnCode = RegSetValueEx(ParmsKey, // Registry handle ! 530: ValueName, // Name of item ! 531: 0, // Reserved 0 ! 532: REG_DWORD, // Data type ! 533: (LPBYTE)&Value, // The value ! 534: sizeof(Value)); // Data length ! 535: ! 536: // ! 537: // Free the handles we created ! 538: // ! 539: ! 540: RegCloseKey(ParmsKey); ! 541: ! 542: return ReturnCode; ! 543: } ! 544: ! 545: /*************************************************************************** ! 546: * ! 547: * Function : ! 548: * DrvCreateParamsKey ! 549: * ! 550: * Parameters : ! 551: * RegAccess Registry access info ! 552: * ! 553: * Return code : ! 554: * ! 555: * Standard error code (see winerror.h) ! 556: * ! 557: * Description : ! 558: * ! 559: * Create the device parameters section under the ! 560: * services node if it does not already exist. No values are ! 561: * written to the key. ! 562: * ! 563: ***************************************************************************/ ! 564: ! 565: LONG ! 566: DrvCreateParamsKey( ! 567: PREG_ACCESS RegAccess) ! 568: { ! 569: HKEY ServiceNodeKey; ! 570: HKEY ParmsKey; ! 571: LONG ReturnCode; ! 572: ! 573: ServiceNodeKey = DrvOpenRegKey(RegAccess->DriverName); ! 574: ! 575: if (ServiceNodeKey == NULL) { ! 576: return ERROR_FILE_NOT_FOUND; ! 577: } ! 578: ! 579: // ! 580: // Try to get a handle to the parameters subkey - which may ! 581: // involve creating the subkey ! 582: // ! 583: ! 584: ReturnCode = RegCreateKey(ServiceNodeKey, STR_DEVICE_DATA, &ParmsKey); ! 585: ! 586: RegCloseKey(ServiceNodeKey); ! 587: ! 588: if (ReturnCode == ERROR_SUCCESS) { ! 589: RegCloseKey(ParmsKey); ! 590: } ! 591: ! 592: return ReturnCode; ! 593: ! 594: } ! 595: ! 596: /*************************************************************************** ! 597: * ! 598: * Function : ! 599: * DrvQueryDeviceParameter ! 600: * ! 601: * Parameters : ! 602: * ServiceNodeKey Handle to the device services node key ! 603: * ValueName Name of value to query ! 604: * pValue Returned value ! 605: * ! 606: * Return code : ! 607: * ! 608: * Standard error code (see winerror.h) ! 609: * ! 610: * Description : ! 611: * ! 612: * Add the value to the device parameters section under the ! 613: * services node. ! 614: * This section is created if it does not already exist. ! 615: * ! 616: ***************************************************************************/ ! 617: ! 618: LONG ! 619: DrvQueryDeviceParameter( ! 620: PREG_ACCESS RegAccess, ! 621: LPTSTR ValueName, ! 622: PDWORD pValue) ! 623: { ! 624: HKEY ServiceNodeKey; ! 625: HKEY ParmsKey; ! 626: LONG ReturnCode; ! 627: DWORD Index; ! 628: ! 629: ServiceNodeKey = DrvOpenRegKey(RegAccess->DriverName); ! 630: ! 631: if (ServiceNodeKey == NULL) { ! 632: return ERROR_FILE_NOT_FOUND; ! 633: } ! 634: ! 635: // ! 636: // First try to get a handle to the parameters subkey ! 637: // ! 638: ! 639: ReturnCode = RegOpenKey(ServiceNodeKey, STR_DEVICE_DATA, &ParmsKey); ! 640: RegCloseKey(ServiceNodeKey); ! 641: ! 642: if (ReturnCode != ERROR_SUCCESS) { ! 643: return ReturnCode; ! 644: } ! 645: ! 646: // ! 647: // That was OK ! 648: // Now we have to laboriously search the key values to ! 649: // see if one corresponds to the one we want ! 650: // ! 651: ! 652: ! 653: for (Index = 0; ; Index++) { // Enumerate key values ! 654: ! 655: TCHAR ThisValueName[MAX_PATH]; ! 656: DWORD NameLength; ! 657: DWORD Type; ! 658: DWORD Value; ! 659: DWORD ValueLength; ! 660: ! 661: NameLength = MAX_PATH; ! 662: NameLength = sizeof(ThisValueName); ! 663: ValueLength = sizeof(Value); ! 664: ! 665: ReturnCode = RegEnumValue(ParmsKey, // Handle to key ! 666: Index, // Index of value ! 667: ThisValueName, // Where to put the name ! 668: &NameLength, // Length of the name ! 669: NULL, // Reserved NULL ! 670: &Type, // returns REG_... type ! 671: (LPBYTE)&Value, // Where to put the value ! 672: &ValueLength); // Max length of data ! 673: ! 674: if (ReturnCode == ERROR_SUCCESS) { ! 675: // ! 676: // We've found something - does it's name match the ! 677: // name we're looking for ? ! 678: // ! 679: ! 680: if (0 == wcsicmp(ValueName, ThisValueName)) { ! 681: RegCloseKey(ParmsKey); ! 682: ! 683: // ! 684: // If it's the wrong type there's something ! 685: // wrong !! ! 686: // ! 687: ! 688: if (Type == REG_DWORD) { ! 689: ! 690: // ! 691: // Return Value to caller ! 692: // ! 693: ! 694: *pValue = Value; ! 695: return ERROR_SUCCESS; ! 696: } else { ! 697: return ERROR_FILE_NOT_FOUND; ! 698: } ! 699: } ! 700: } else { ! 701: // ! 702: // We didn't find the value with the name we were ! 703: // looking for so return the default ! 704: // ! 705: ! 706: RegCloseKey(ParmsKey); ! 707: return ReturnCode; ! 708: } ! 709: } ! 710: } ! 711: ! 712: ! 713: /*************************************************************************** ! 714: * ! 715: * Function : ! 716: * DrvLoadKernelDriver ! 717: * ! 718: * Parameters : ! 719: * Drivername Name of driver to load ! 720: * ! 721: * Return code : ! 722: * ! 723: * TRUE if successful, otherwise FALSE ! 724: * ! 725: * Description : ! 726: * ! 727: * Call StartService to load the driver. This assumes the services ! 728: * name is the driver name ! 729: * ! 730: ***************************************************************************/ ! 731: ! 732: BOOL ! 733: DrvLoadKernelDriver( ! 734: PREG_ACCESS RegAccess) ! 735: { ! 736: SC_HANDLE ServiceHandle; ! 737: BOOL Success; ! 738: ServiceHandle = DrvOpenService(RegAccess); ! 739: ! 740: if (ServiceHandle == NULL) { ! 741: return FALSE; ! 742: } ! 743: ! 744: /* ! 745: * StartService causes the system to try to load the kernel driver ! 746: */ ! 747: ! 748: Success = StartService(ServiceHandle, 0, NULL); ! 749: ! 750: /* ! 751: * If this was successful we can change the start type to system ! 752: * start ! 753: */ ! 754: ! 755: if (Success) { ! 756: Success = ChangeServiceConfig(ServiceHandle, ! 757: SERVICE_NO_CHANGE, ! 758: SERVICE_SYSTEM_START, ! 759: SERVICE_NO_CHANGE, ! 760: NULL, ! 761: NULL, ! 762: NULL, ! 763: NULL, ! 764: NULL, ! 765: NULL, ! 766: NULL); ! 767: } ! 768: DrvCloseService(RegAccess, ServiceHandle); ! 769: return Success; ! 770: } ! 771: ! 772: /*************************************************************************** ! 773: * ! 774: * Function : ! 775: * DrvUnLoadKernelDriver ! 776: * ! 777: * Parameters : ! 778: * RegAccess Access variables to registry and Service control ! 779: * manager ! 780: * ! 781: * Return code : ! 782: * ! 783: * TRUE if successful, otherwise FALSE ! 784: * ! 785: * Description : ! 786: * ! 787: * Call ControlService to unload the driver. This assumes the services ! 788: * name is the driver name ! 789: * ! 790: ***************************************************************************/ ! 791: ! 792: BOOL ! 793: DrvUnloadKernelDriver( ! 794: PREG_ACCESS RegAccess) ! 795: { ! 796: SERVICE_STATUS ServiceStatus; ! 797: SC_HANDLE ServiceHandle; ! 798: BOOL Success; ! 799: ! 800: ! 801: ServiceHandle = DrvOpenService(RegAccess); ! 802: if (ServiceHandle == NULL) { ! 803: return GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST; ! 804: } ! 805: ! 806: /* ! 807: * Set it not to load at system start until we've reconfigured ! 808: */ ! 809: ! 810: Success = ChangeServiceConfig(ServiceHandle, ! 811: SERVICE_NO_CHANGE, ! 812: SERVICE_DEMAND_START, ! 813: SERVICE_NO_CHANGE, ! 814: NULL, ! 815: NULL, ! 816: NULL, ! 817: NULL, ! 818: NULL, ! 819: NULL, ! 820: NULL); ! 821: ! 822: if (Success) { ! 823: /* ! 824: * Don't try to unload if it's not loaded ! 825: */ ! 826: ! 827: if (DrvIsDriverLoaded(RegAccess)) { ! 828: ! 829: /* ! 830: * Note that the driver object name will not be found if ! 831: * the driver is not loaded. However, the services manager may ! 832: * get in first and decide that the driver file does not exist. ! 833: */ ! 834: ! 835: Success = ControlService(ServiceHandle, ! 836: SERVICE_CONTROL_STOP, ! 837: &ServiceStatus); ! 838: ! 839: } ! 840: ! 841: } ! 842: ! 843: DrvCloseService(RegAccess, ServiceHandle); ! 844: return Success; ! 845: } ! 846: ! 847: /*************************************************************************** ! 848: * ! 849: * Function : ! 850: * ! 851: * DrvIsDriverLoaded ! 852: * ! 853: * Parameters : ! 854: * ! 855: * RegAccess Access variables to registry and Service control ! 856: * manager ! 857: * ! 858: * Return code : ! 859: * ! 860: * TRUE if successful, otherwise FALSE ! 861: * ! 862: * Description : ! 863: * ! 864: * See if a service by our name is started. ! 865: * Note - this assumes that we think our service is installed ! 866: * ! 867: ***************************************************************************/ ! 868: BOOL ! 869: DrvIsDriverLoaded( ! 870: PREG_ACCESS RegAccess) ! 871: { ! 872: SERVICE_STATUS ServiceStatus; ! 873: SC_HANDLE ServiceHandle; ! 874: BOOL Success; ! 875: ServiceHandle = DrvOpenService(RegAccess); ! 876: if (ServiceHandle == NULL) { ! 877: return FALSE; ! 878: } ! 879: ! 880: ! 881: if (!QueryServiceStatus(ServiceHandle, &ServiceStatus)) { ! 882: DrvCloseService(RegAccess, ServiceHandle); ! 883: return FALSE; ! 884: } ! 885: ! 886: Success = ServiceStatus.dwServiceType == SERVICE_KERNEL_DRIVER && ! 887: ServiceStatus.dwCurrentState == SERVICE_RUNNING; ! 888: ! 889: DrvCloseService(RegAccess, ServiceHandle); ! 890: return Success; ! 891: } ! 892: ! 893: ! 894: /*************************************************************************** ! 895: * ! 896: * Function : ! 897: * ! 898: * DrvConfigureDriver ! 899: * ! 900: * Parameters : ! 901: * ! 902: * RegAccess Access variables to registry and Service control ! 903: * manager ! 904: * ! 905: * DriverName Name of the driver ! 906: * ! 907: * DriverType Type of driver (see registry.h) ! 908: * ! 909: * SetParms Callback to set the registry parameters ! 910: * ! 911: * Context Context value for callback ! 912: * ! 913: * Return code : ! 914: * ! 915: * TRUE if successful, otherwise FALSE ! 916: * ! 917: * Description : ! 918: * ! 919: * Performs the necessary operations to (re) configure a driver : ! 920: * ! 921: * 1. If the driver is already installed : ! 922: * ! 923: * Unload it if necessary ! 924: * ! 925: * Set its start type to Demand until we know we're safe ! 926: * (This is so the system won't load a bad config if we crash) ! 927: * ! 928: * 2. If the driver is not installed create its service entry in the ! 929: * registry. ! 930: * ! 931: * 3. Run the callback to set up the driver's parameters ! 932: * ! 933: * 4. Load the driver ! 934: * ! 935: * 5. If the load returns success set the start type to System start ! 936: * ! 937: ***************************************************************************/ ! 938: ! 939: BOOL DrvConfigureDriver( ! 940: PREG_ACCESS RegAccess, ! 941: LPTSTR DriverName, ! 942: SOUND_KERNEL_MODE_DRIVER_TYPE ! 943: DriverType, ! 944: BOOL (* SetParms )(PVOID), ! 945: PVOID Context) ! 946: { ! 947: return ! 948: ! 949: /* ! 950: * If there isn't a services node create one - this is done first ! 951: * because this is how the driver name gets into the REG_ACCESS ! 952: * structure ! 953: */ ! 954: ! 955: DrvCreateServicesNode( ! 956: DriverName, ! 957: DriverType, ! 958: RegAccess, ! 959: TRUE) ! 960: ! 961: && ! 962: ! 963: /* ! 964: * Unload driver if it's loaded ! 965: */ ! 966: ! 967: DrvUnloadKernelDriver(RegAccess) ! 968: ! 969: && ! 970: ! 971: /* ! 972: * Run the callback ! 973: */ ! 974: ! 975: (SetParms == NULL || (*SetParms)(Context)) ! 976: ! 977: && ! 978: ! 979: /* ! 980: * Try reloading the driver ! 981: */ ! 982: ! 983: DrvLoadKernelDriver(RegAccess) ! 984: ! 985: ; ! 986: ! 987: } ! 988: ! 989: ! 990: /*************************************************************************** ! 991: * ! 992: * Function : ! 993: * ! 994: * DrvRemoveDriver ! 995: * ! 996: * Parameters : ! 997: * ! 998: * RegAccess Access variables to registry and Service control ! 999: * manager ! 1000: * ! 1001: * Return code : ! 1002: * ! 1003: * DRVCNF_CANCEL - Error occurred ! 1004: * ! 1005: * DRVCNF_OK - Registry entry delete but driver wasn't loaded ! 1006: * ! 1007: * DRVCNF_RESTART - Driver unloaded and registry entry deleted ! 1008: * ! 1009: * Description : ! 1010: * ! 1011: * Unload the driver and remove its service control entry ! 1012: * ! 1013: ***************************************************************************/ ! 1014: ! 1015: LRESULT DrvRemoveDriver( ! 1016: PREG_ACCESS RegAccess) ! 1017: { ! 1018: BOOL Loaded; ! 1019: ! 1020: Loaded = DrvIsDriverLoaded(RegAccess); ! 1021: ! 1022: if ((!Loaded || DrvUnloadKernelDriver(RegAccess)) && ! 1023: DrvDeleteServicesNode(RegAccess)) { ! 1024: return Loaded ? DRVCNF_RESTART : DRVCNF_OK; ! 1025: } else { ! 1026: return DRVCNF_CANCEL; ! 1027: } ! 1028: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.