为什么 BluetoothSetLocalServiceInfo 抛出错误 1314?

why does BluetoothSetLocalServiceInfo throw error 1314?

我一直在尝试构建一个 BT 应用程序。我想使用 BluetoothSetLocalServiceInfo 但我收到错误 1314(客户端不持有所需的权限)。 我使用来自 windows 驱动程序的 echo 蓝牙示例。这是我修改后的代码:

DEFINE_GUID(BTHECHOSAMPLE_SVC_GUID, 0xc07508f2, 0xb970, 0x43ca, 0xb5, 0xdd, 0xcc, 0x4f, 0x23, 0x91, 0xbe, 0xf4);
wchar_t name[17] = L"BthEchoSampleSrv";
extern __declspec(selectany) const PWSTR BthEchoSampleSvcName = name;
/* fc71b33d-d528-4763-a86c-78777c7bcd7b */
DEFINE_GUID(BTHECHOSAMPLE_DEVICE_INTERFACE, 0xfc71b33d, 0xd528, 0x4763, 0xa8, 0x6c, 0x78, 0x77, 0x7c, 0x7b, 0xcd, 0x7b);

int main(){

  DWORD err = ERROR_SUCCESS;
  BLUETOOTH_LOCAL_SERVICE_INFO SvcInfo = { 0 };
  SvcInfo.Enabled = true;

  if (FAILED(StringCbCopyW(SvcInfo.szName, sizeof(SvcInfo.szName), BthEchoSampleSvcName)))
  {
    printf("Copying svc name failed\n");
    goto exit;
  }

  std::cout<<"Name of the device: "<< SvcInfo.szName<<std::endl;

  if (ERROR_SUCCESS != (err = BluetoothSetLocalServiceInfo(
    NULL, //callee would select the first found radio
    &BTHECHOSAMPLE_SVC_GUID,
    0,
    &SvcInfo
  )))
  {
    printf("BluetoothSetLocalServiceInfo failed, err = %d\n", err);
    goto exit;
  }
exit:
  return err;
}

我 运行 命令行中的代码(以管理员身份打开),我将应用程序的属性更改为 运行 具有管理员权限。我错过了什么?

错误 1314 是 ERROR_PRIVILEGE_NOT_HELD。根据 BluetoothSetLocalServiceInfo() 文档:

The BluetoothSetLocalServiceInfo function returns the following values:

...

STATUS_PRIVILEGE_NOT_HELD
The caller does not have the required privileges. See the Remarks section for information about how to elevate privileges.

备注说:

Warning
The process that calls BluetoothSetLocalServiceInfo must have the SE_LOAD_DRIVER_NAME privilege. A process running in the system or an administrator context can elevate its privilege by using the SDK LookupPrivilegeValue and AdjustTokenPrivileges functions. For more information about this see Installing a Bluetooth Device.

所以,这意味着:

  • 您的应用 运行 的用户帐户根本没有该权限
  • 您的应用未通过 AdjustTokenPrivileges() 启用权限。

Installing a Bluetooth Device 文档提供了启用 SE_LOAD_DRIVER_NAME 权限的示例:

The installation application must call the user-mode API BluetoothSetLocalServiceInfo. However, before the application can call this API, the application must have the SE_LOAD_DRIVER_NAME security privilege. The following code example demonstrates how to obtain this privilege. Note, the example does not demonstrate error handling.

HANDLE procToken;
LUID luid;
TOKEN_PRIVILEGES tp;

OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &procToken);

LookupPrivilegeValue(NULL, SE_LOAD_DRIVER_NAME, &luid);

Tp.PrivilegeCount = 1;
Tp.privileges[0].Luid = luid;
Tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

AdjustTokenPrivileges(procToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD)NULL)

有关详细信息,请参阅 MSDN 上的 Changing Privileges in a Token and Enabling and Disabling Privileges in C++