After I run Hyper Terminal or Docklight, my program works (writes and reads OK). But if I never run any of those, all my reads fail.
So I guess I must be missing something in my serial port initialization code, but I can't figure out what. Here it is:
Serial port initialization:
bool CSerialPortDrivenHardware::InitSerialPort(){
m_SerialPort.Config( m_SerialPortConfig );
bool success = ( m_SerialPort.Open( m_SerialPortName ) == TRUE );
if( !success )
Log( LOG_TYPE_ERROR, "CSerialPortDrivenHardware", "InitSerialPort", "Could not establish serial port connection" );
else{
m_SerialPort.SetControlBit( DTR_CONTROL_BIT );
m_SerialPort.SetControlBit( RTS_CONTROL_BIT );
}
return success;
}
Serial port class (relevant code):
BOOL CSerialPort::Config( SConfig sConfig ) {
if( !m_hFile ) return FALSE;
DCB dcb;
if ( !::GetCommState( m_hFile, &dcb ) ) {
m_dwLastError = ::GetLastError();
return FALSE;
}
dcb.BaudRate = sConfig.dwBaudRate;
dcb.Parity = sConfig.bParity;
dcb.StopBits = sConfig.bStopBits;
dcb.ByteSize = sConfig.bDataBits;
if ( !::SetCommState( m_hFile, &dcb ) ) {
m_dwLastError = ::GetLastError();
return FALSE;
}
::Sleep(200);
return TRUE;
}
BOOL CSerialPort::Open( LPCSTR cszCOM ) {
CHAR sPortName[256] = "\\\\.\\";
strcat_s( sPortName, cszCOM );
m_strPortName = sPortName;
if( m_hFile )
return FALSE;
m_hFile = ::CreateFile( m_strPortName.c_str(), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if( m_hFile == INVALID_HANDLE_VALUE )
m_hFile = NULL;
if( !m_hFile )
return FALSE;
SetFlags( 0 );
return TRUE;
}
void CSerialPort::SetFlags( DWORD dwFlags ) {
if( dwFlags & READMODE_BLOCKING )
SetTimeout( INFINITE );
else
SetTimeout( 0 );
}
void CSerialPort::SetTimeout( DWORD dwTimeout ) {
COMMTIMEOUTS sCommTimeouts;
if( !::GetCommTimeouts( m_hFile, &sCommTimeouts ) ) {
m_dwLastError = ::GetLastError();
return;
}
sCommTimeouts.ReadIntervalTimeout = 0;
sCommTimeouts.ReadTotalTimeoutMultiplier = 0;
sCommTimeouts.ReadTotalTimeoutConstant = dwTimeout;
if ( !::SetCommTimeouts( m_hFile, &sCommTimeouts ) )
m_dwLastError = ::GetLastError();
}
BOOL CSerialPort::SetControlBit( ESerialPortControlBit eControlBit ) {
if( !m_hFile )
return FALSE;
BOOL bResult = FALSE;
switch( eControlBit ) {
case DTR_CONTROL_BIT:
bResult = ::EscapeCommFunction( m_hFile, SETDTR );
break;
case RTS_CONTROL_BIT:
bResult = ::EscapeCommFunction( m_hFile, SETRTS );
break;
}
return bResult;
}
You should first open port, than configure. And your code does it in opposite direction. That's why your configure code does not work and port just opens with default settings.
Just look your code:
BOOL CSerialPort::Config( SConfig sConfig ) {
if( !m_hFile ) return FALSE;
....
And m_hFile is set in CSerialPort::Open
BOOL CSerialPort::Open( LPCSTR cszCOM ) {
CHAR sPortName[256] = "\\\\.\\";
strcat_s( sPortName, cszCOM );
m_strPortName = sPortName;
if( m_hFile )
return FALSE;
m_hFile = ::CreateFile( m_strPortName.c_str(), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
.....
It seems your hyper terminal program adjust default settings and that's why when you open port after using `hyper terminal it opens with correct settings.
Related
I'm developing an application which captures frames using DXGI mechanism from an application.
First creation of the IDXGIOutputDuplication is correct. When the application changes its display (for example from fullscreen to windowed or vice versa), the frame acquire failed (expected behaviour), then I recreate the IDXGIOutputDuplication and regularly the call to DuplicateOutput crash.
Below creation of the D3d11 device:
D3D_FEATURE_LEVEL FeatureLevels[] =
{
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_1
};
UINT NumFeatureLevels = ARRAYSIZE( FeatureLevels );
D3D_FEATURE_LEVEL FeatureLevel = D3D_FEATURE_LEVEL_11_1;
D3D11CreateDevice( _pDxgiAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0, FeatureLevels, NumFeatureLevels, D3D11_SDK_VERSION, &_pD3D11Device, &FeatureLevel, &_pD3D11DeviceCtx );
_pDxgiAdapter is created before the device.
Below creation of the IDXGIOutputDuplication:
int DxgiVideoCapture::open() {
findDxgiAdapter();
if( nullptr != _pDxgiAdapter ) {
// Duplicate output
uint32_t ui32OutputIndex = 0;
HRESULT hr = S_OK;
while( SUCCEEDED( hr ) ) {
IDXGIOutput* pDxgiOutput = nullptr;
hr = _pDxgiAdapter->EnumOutputs( ui32OutputIndex, &pDxgiOutput );
if( SUCCEEDED( hr ) ) {
IDXGIOutput1* pDxgiOutput1 = nullptr;
if( SUCCEEDED ( pDxgiOutput->QueryInterface( __uuidof( IDXGIOutput1 ), ( void** )&pDxgiOutput1 ) ) ) {
uint32_t ui32EnumMode = 0;
uint32_t ui32Flags = 0xffffffff;
}
if( SUCCEEDED ( pDxgiOutput->QueryInterface( __uuidof( IDXGIOutput1 ), ( void** )&_pDxgiOutput1 ) ) ) {
LOGI( "/!\\ Call which crash regularly /!\\" );
HRESULT hrDup = _pDxgiOutput1->DuplicateOutput( _pD3D11Device, &_pOutputDuplication );
if( SUCCEEDED( hrDup ) ) {
LOGI( "Output duplication created." );
} else {
switch( hrDup ) {
case E_INVALIDARG :
{
LOGW( "Invalid device or output already duplicated" );
}
break;
case E_ACCESSDENIED :
{
LOGW( "Access denied" );
}
break;
case DXGI_ERROR_UNSUPPORTED :
{
LOGW( "DXGI_ERROR_UNSUPPORTED" );
}
break;
case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE :
{
LOGW( "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE" );
}
break;
case DXGI_ERROR_SESSION_DISCONNECTED :
{
LOGW( "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE" );
}
break;
default:
{
LOGW( "default" );
}
}
} else {
LOGE( "Unable to retrieve interface creating the ouput duplication" );
}
}
pDxgiOutput->Release();
}
ui32OutputIndex++;
}
return RET_OK;
}
Below the frame acquisition:
int DxgiVideoCapture::captureGameFrame() {
int iRet = RET_ERROR;
ID3D11Texture2D* pCapturedTexture = nullptr;
DXGI_OUTDUPL_FRAME_INFO frameInfo;
ZeroMemory(&frameInfo, sizeof(frameInfo));
HRESULT hr = _pOutputDuplication->AcquireNextFrame( 1000, &frameInfo, &_pDxgiResource );
if( FAILED( hr ) ) {
if( hr == DXGI_ERROR_WAIT_TIMEOUT ) {
LOGW( "Wait for %d ms timed out", 1000);
}
if (hr == DXGI_ERROR_INVALID_CALL) {
LOGW( "Invalid Call, previous frame not released?" );
}
if (hr == DXGI_ERROR_ACCESS_LOST) {
LOGW( "Error Access lost - is it a game end ?" );
}
iRet = RET_RESET_CAPTURE;
return iRet;
}
if( FAILED( hr = _pDxgiResource->QueryInterface( __uuidof( ID3D11Texture2D ), ( void** ) &pCapturedTexture ) ) ) {
LOGW( "unable to retrieve D3D11 texture 0x%x", hr );
return RET_WARNING;
} else {
// Store window of the game
D3D11_TEXTURE2D_DESC d3D11TextureDesc;
pCapturedTexture->GetDesc( &d3D11TextureDesc );
// Compute the zone to extract.
D3D11_BOX srcBox;
memset( &srcBox, 0, sizeof( srcBox ) );
if( _pGameWindow->getLeftPos() > 0 ) {
srcBox.left = _pGameWindow->getLeftPos();
}
if( _pGameWindow->getTopPos() > 0 ) {
srcBox.top = _pGameWindow->getTopPos();
}
srcBox.front = 0;
srcBox.right = _pGameWindow->getLeftPos() + _pGameWindow->getWidth();
if( srcBox.right > _pGameWindow->getMonitorWidth() ) {
srcBox.right = _pGameWindow->getMonitorWidth();
}
if( ( srcBox.right - srcBox.left ) % 2 != 0 ) {
srcBox.right--;
}
srcBox.bottom = _pGameWindow->getTopPos() + _pGameWindow->getHeight();
if( srcBox.bottom > _pGameWindow->getMonitorHeight() ) {
srcBox.bottom = _pGameWindow->getMonitorHeight();
}
if( ( srcBox.bottom - srcBox.top ) % 2 != 0 ) {
srcBox.bottom--;
}
srcBox.back = 1;
// AVFrame info are udpate just when the captured game window and the texture are diffrent.
// In the same time texture is reallocated.
if( ( ( srcBox.right - srcBox.left ) != _CapturedTextureDesc.Width )
|| ( ( srcBox.bottom - srcBox.top ) != _CapturedTextureDesc.Height )
) {
LOGD( "Game window: %dx%d ; %d->%d", _pGameWindow->getLeftPos(), _pGameWindow->getTopPos(), _pGameWindow->getWidth(), _pGameWindow->getHeight() );
LOGD( "Texture creation %dx%d -> %dx%d", srcBox.left, srcBox.top, srcBox.right, srcBox.bottom );
// Create the new texture
iRet = createCapturedTexture( srcBox.right - srcBox.left, srcBox.bottom - srcBox.top );
}
DirectX11Util::GetInstance()->getD3D11DeviceContext()->CopySubresourceRegion( _pGameTexture, 0, 0, 0, 0, pCapturedTexture, 0, &srcBox );
}
if( nullptr != _pDxgiResource ) {
_pOutputDuplication->ReleaseFrame();
pCapturedTexture->Release();
_pDxgiResource->Release();
_pDxgiResource = nullptr;
}
iRet = RET_OK;
return iRet;
}
Below the release of the D3d11 capture before recreation of the IDXGIOutputDuplication:
int DxgiVideoCapture::close() {
if( nullptr != _pGameTexture ) {
ZeroMemory( &_CapturedTextureDesc, sizeof( D3D11_TEXTURE2D_DESC ) );
_pGameTexture->Release();
_pGameTexture = nullptr;
}
if( nullptr != _pDxgiResource ){
_pOutputDuplication->ReleaseFrame();
_pDxgiResource->Release();
_pDxgiResource = nullptr;
}
if( nullptr != _pOutputDuplication ) {
_pOutputDuplication->Release();
_pOutputDuplication = nullptr;
}
return RET_OK;
}
What I would like to know is how can I invest this crash (application ends without any message). To be more accurate I cross compile my application, but the behaviour seems the same. Do you have any idea how to invest this issue ?
Tell me if you want more details.
Thanks in advance !
I'm developing a business application with windows 10, that should automatically connect to a given bluetooth speaker/headset (Jabra FREEWAY v5.7.0).
Using the BluetoothAPIs.h this works well so far. Problem is, it does not show up as audio device under windows. I can't play a test sound (or any other) on it.
How do I pair the device as audio device? or are there any subsequent steps to set the device as audio?
We have similar code functioning for a mobile printer, there seems no need to do extra steps there.
Connecting the device (Jabra) with the given windows opporunities shows it correctly as audio device.
BOOL CALLBACK BTHeadsetAuthCallbackEx(__in_opt LPVOID /*pvParam*/, __in PBLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS pAuthCallbackParams)
{
BLUETOOTH_AUTHENTICATE_RESPONSE resp;
resp.bthAddressRemote = pAuthCallbackParams->deviceInfo.Address;
resp.authMethod = pAuthCallbackParams->authenticationMethod;
resp.negativeResponse = FALSE;
resp.passkeyInfo.passkey = pAuthCallbackParams->Passkey;
DWORD ret = BluetoothSendAuthenticationResponseEx( NULL, &resp );
if( ret != ERROR_SUCCESS )
{
logError( "BluetoothSendAuthenticationResponseEx failed with %u", ret );
return FALSE;
}
return TRUE;
}
BLUETOOTH_DEVICE_INFO deviceInfo = { sizeof(BLUETOOTH_DEVICE_INFO) };
deviceInfo.Address.ullLong = device->getAddress();
HBLUETOOTH_AUTHENTICATION_REGISTRATION regHandle;
DWORD err = BluetoothRegisterForAuthenticationEx( &deviceInfo, ®Handle, (PFN_AUTHENTICATION_CALLBACK_EX)&BTHeadsetAuthCallbackEx, NULL );
if( err != ERROR_SUCCESS )
{
logError( "BluetoothRegisterForAuthenticationEx failed with %u", err );
return false;
}
err = BluetoothAuthenticateDevice( NULL, NULL, &deviceInfo, L"0000", 4 );
if( err != ERROR_SUCCESS )
{
BluetoothUnregisterAuthentication( regHandle );
logError( "BluetoothAuthenticateDevice failed with %u", err );
return false;
}
BluetoothUnregisterAuthentication( regHandle );
As pointed out by Mike Petrichenko I needed to call BluetoothSetServiceState() with a correct service GUID (hands-free devices in my case), which I found here: https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-bluetooth
Complete code:
BOOL CALLBACK BTHeadsetAuthCallbackEx(__in_opt LPVOID /*pvParam*/, __in PBLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS pAuthCallbackParams)
{
BLUETOOTH_AUTHENTICATE_RESPONSE resp;
resp.bthAddressRemote = pAuthCallbackParams->deviceInfo.Address;
resp.authMethod = pAuthCallbackParams->authenticationMethod;
resp.negativeResponse = FALSE;
resp.passkeyInfo.passkey = pAuthCallbackParams->Passkey;
DWORD ret = BluetoothSendAuthenticationResponseEx( NULL, &resp );
if( ret != ERROR_SUCCESS )
{
logError( "BluetoothSendAuthenticationResponseEx failed with %u", ret );
return FALSE;
}
return TRUE;
}
BLUETOOTH_DEVICE_INFO deviceInfo = { sizeof(BLUETOOTH_DEVICE_INFO) };
deviceInfo.Address.ullLong = device->getAddress();
HBLUETOOTH_AUTHENTICATION_REGISTRATION regHandle;
DWORD err = BluetoothRegisterForAuthenticationEx( &deviceInfo, ®Handle, (PFN_AUTHENTICATION_CALLBACK_EX)&BTHeadsetAuthCallbackEx, NULL );
if( err != ERROR_SUCCESS )
{
logError( "BluetoothRegisterForAuthenticationEx failed with %u", err );
return false;
}
err = BluetoothAuthenticateDevice( NULL, NULL, &deviceInfo, L"0000", 4 );
if( err != ERROR_SUCCESS )
{
BluetoothUnregisterAuthentication( regHandle );
logError( "BluetoothAuthenticateDevice failed with %u", err );
return false;
}
BluetoothUnregisterAuthentication( regHandle );
HANDLE btHeadset;
BLUETOOTH_FIND_RADIO_PARAMS rfind = { sizeof( rfind ) };
BluetoothFindFirstRadio( &rfind, &btHeadset );
GUID id = { 0x0000111e, 0x0000, 0x1000, { 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb} };
err = BluetoothSetServiceState( &btHeadset, &deviceInfo, &id, BLUETOOTH_SERVICE_ENABLE );
if( err != ERROR_SUCCESS )
{
logError( "BluetoothSetServiceState failed with %u", err );
}
logNorm( "BluetoothSetServiceState successfull" );
note: this is not completely fool proof. I'm using the first device found with empty search parameters. Some refining will be implemented there.
How could I decide if my application is running under LocalSystem Account or not? Is there an easy way to do that?
Thanks!
Thanks for your help, but I might have found a way. Not the best, I know, but it works.
BOOL CheckIfRunningAsSYSTEM( VOID )
{
DWORD i, dwSize = 0, dwResult = 0;
HANDLE hToken;
PTOKEN_USER Ptoken_User;
// Open a handle to the access token for the calling process.
if ( !OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ) )
{
printf( "OpenProcessToken Error %u\n", GetLastError() );
return FALSE;
}
// Call GetTokenInformation to get the buffer size.
if ( !GetTokenInformation( hToken, TokenUser, NULL, dwSize, &dwSize ) )
{
dwResult = GetLastError();
if ( dwResult != ERROR_INSUFFICIENT_BUFFER )
{
printf( "GetTokenInformation Error %u\n", dwResult );
return FALSE;
}
}
// Allocate the buffer.
Ptoken_User = ( PTOKEN_USER )GlobalAlloc( GPTR, dwSize );
// Call GetTokenInformation again to get the group information.
if ( !GetTokenInformation( hToken, TokenUser, Ptoken_User, dwSize, &dwSize ) )
{
printf( "GetTokenInformation Error %u\n", GetLastError() );
return FALSE;
}
LPWSTR SID = NULL;
if ( !ConvertSidToStringSidW( Ptoken_User->User.Sid, &SID ) )
{
printf( "\nConvertSidToStringSidW failed. Error = %d", GetLastError() );
return FALSE;
}
else printf( "\nConvertSidToStringSidW succeeded." );
if ( _wcsicmp( L"S-1-5-18", SID ) == 0 ) printf( "\nRunning under SYSTEM" );
else printf( "\nNOT running under SYSTEM" );
if ( Ptoken_User ) GlobalFree( Ptoken_User );
return TRUE;
}//CheckIfRunningAsSYSTEM
How do I find the port name for a bluetooth device with a specific device name?
I have this code, which enumerates all bluetooth devices, but doesn't give me their port name:
HBLUETOOTH_DEVICE_FIND founded_device;
BLUETOOTH_DEVICE_INFO device_info;
device_info.dwSize = sizeof(device_info);
BLUETOOTH_DEVICE_SEARCH_PARAMS search_criteria;
search_criteria.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS);
search_criteria.fReturnAuthenticated = TRUE;
search_criteria.fReturnRemembered = FALSE;
search_criteria.fReturnConnected = FALSE;
search_criteria.fReturnUnknown = FALSE;
search_criteria.fIssueInquiry = FALSE;
search_criteria.cTimeoutMultiplier = 0;
founded_device = BluetoothFindFirstDevice(&search_criteria, &device_info);
if(founded_device == NULL)
return -1;
do {
wstring ws = device_info.szName;
cout << string(ws.begin(), ws.end()) << endl;
} while (BluetoothFindNextDevice(founded_device, &device_info));
And then I have this code, which enumerates all port names but doesn't give me the device name:
DWORD bytesNeeded = 0;
DWORD portCount = 0;
BOOL ret = EnumPorts(nullptr, 2, nullptr, 0, &bytesNeeded, &portCount);
BYTE *ports = new BYTE[bytesNeeded];
if(EnumPorts(nullptr, 2, (LPBYTE)ports, bytesNeeded, &bytesNeeded, &portCount))
{
PORT_INFO_2 *portInfo = (PORT_INFO_2*)ports;
for(DWORD i = 0; i < portCount; ++i)
cout << portInfo[i].pPortName << endl;
}
delete [] ports;
I need to automatically connect to a specific device when my app is started, so I need to either get the port name for the bluetooth device in the first piece of code so I can connect to it, or check each portname in the second piece of code to make sure it's the right device before connecting to it.
How do I do it?
I remember struggling with this in the past.
the only solution i found was to use sockets for communicating with the Bluetooth device using its address, then use the send() and recv() methods for communicating with the device.
// assuming you have the BT device address in blueToothDeviceAddr;
char blueToothDeviceAddr[18];
SOCKET sock;
SOCKADDR_BTH sa = { 0,0,0,0 };
int sa_len = sizeof(sa);
// initialize windows sockets
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD( 2, 0 );
if( WSAStartup( wVersionRequested, &wsaData ) != 0 )
{
ExitProcess(100);
}
// parse the specified Bluetooth address
if( SOCKET_ERROR == WSAStringToAddress( blueToothDeviceAddr, AF_BTH,
NULL, (LPSOCKADDR) &sa, &sa_len ) )
{
ExitProcess(101);
}
// query it for the right port
// create the socket
sock = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
if( SOCKET_ERROR == sock )
{
ExitProcess(102);
}
// fill in the rest of the SOCKADDR_BTH struct
GUID pService = (GUID)SerialPortServiceClass_UUID;
SOCKADDR_BTH outSA;
sa.port = SDPGetPort(blueToothDeviceAddr, (LPGUID) &pService,&outSA);
if( sa.port == 0 )
{
ExitProcess(103);
}
// in case you have a pass code you need to register for authetication callback
// look the web for this part
// connect to the device
if( SOCKET_ERROR == connect( sock, (LPSOCKADDR) &outSA, sa_len ) )
{
int lastError = GetLastError();
ExitProcess(105);
}
Under the key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\BTHENUM
you can find a subkey which has a list of keys containing the device address.
Under this last key, you can find a subkey named Device Parameters which finally has the PortName value.
The code is written in C++ with MFC libraries and is tested under Windows XP, 7 and 10. I hope it helps you !
// Returns the outgoing COM port of a bluetooth device given by address
int GetBluetoothCOM( CString sAddr )
{
int iPort = 0;
HKEY hKey_1;
DWORD KeyNdx_1 = 0;
DWORD MaxKeyLen_1;
char KeyNam_1[ MAX_PATH + 1 ];
LONG RetVal_1;
sAddr.MakeUpper();
sAddr.Replace( ":", "" );
sAddr.Replace( " ", "" );
// Enumerate keys under: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\BTHENUM
RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Enum\\BTHENUM", NULL, KEY_READ | KEY_ENUMERATE_SUB_KEYS, &hKey_1 );
while( true )
{
MaxKeyLen_1 = MAX_PATH;
RetVal_1 = RegEnumKeyEx( hKey_1, KeyNdx_1, KeyNam_1, &MaxKeyLen_1, NULL, NULL, NULL, NULL );
if( RetVal_1 == ERROR_NO_MORE_ITEMS )
{
break;
}
if( RetVal_1 == ERROR_SUCCESS )
{
HKEY hKey_2;
DWORD KeyNdx_2 = 0;
DWORD MaxKeyLen_2;
char KeyNam_2[ MAX_PATH + 1 ];
LONG RetVal_2;
// Enumerate subkeys
RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Enum\\BTHENUM\\" + CString( KeyNam_1 ), NULL, KEY_READ | KEY_ENUMERATE_SUB_KEYS, &hKey_2 );
while( true )
{
MaxKeyLen_2 = MAX_PATH;
RetVal_2 = RegEnumKeyEx( hKey_2, KeyNdx_2, KeyNam_2, &MaxKeyLen_2, NULL, NULL, NULL, NULL );
if( RetVal_2 == ERROR_NO_MORE_ITEMS )
{
break;
}
if( RetVal_2 == ERROR_SUCCESS )
{
// Find out if the key name contains &ADDRESS_
CString sKey = "SYSTEM\\CurrentControlSet\\Enum\\BTHENUM\\" + CString( KeyNam_1 ) + "\\" + CString( KeyNam_2 );
sKey.MakeUpper();
if( sKey.Find( "&" + sAddr + "_" ) != -1 )
{
HKEY hKey;
char szPort[ 100 + 1 ];
DWORD dwLen = 100;
// I find out the device
RegOpenKeyEx( HKEY_LOCAL_MACHINE, sKey + "\\Device Parameters", 0, KEY_READ, &hKey );
if( RegQueryValueEx( hKey, "PortName", NULL, NULL, ( LPBYTE ) &szPort, &dwLen ) == ERROR_SUCCESS )
{
szPort[ dwLen ] = 0;
CString sPort = CString( szPort );
sPort.MakeUpper();
if( sPort.Find( "COM" ) == -1 )
{
RegCloseKey( hKey );
continue;
}
sPort.Replace( "COM", "" );
sPort.Trim();
iPort = atoi( sPort.GetBuffer() );
if( iPort != 0 )
{
RegCloseKey( hKey );
break;
}
}
RegCloseKey( hKey );
}
}
++KeyNdx_2;
}
RegCloseKey( hKey_2 );
if( iPort != 0 )
{
break;
}
}
++KeyNdx_1;
};
RegCloseKey( hKey_1 );
return iPort;
}
How can I pin application icon to metro start screen in win8 programmatically(c++)? I know how to do it manually. I also know that it will be added automatically once I launch that application.
I found this solution here
BOOL PinToStart( LPCWSTR szFilePath )
{
BOOL bSuccess = FALSE;
// break into file name and path
WCHAR lpszDirectoryName[ MAX_PATH ] = { 0 };
LPCWSTR lpszFileName = ::PathFindFileName( szFilePath );
wcscpy_s( lpszDirectoryName, szFilePath );
::PathRemoveFileSpec( lpszDirectoryName );
// load shell32.dll
HMODULE hShell32 = LoadLibrary( L"SHELL32" );
if( hShell32 != NULL )
{
// get the localized translation of 'Pin to Start' verb
WCHAR szPinToStartLocalized[ MAX_PATH ] = { 0 };
int nPinToStartLocalizedLength = LoadString( (HINSTANCE)hShell32, 51201, szPinToStartLocalized, MAX_PATH );
if( nPinToStartLocalizedLength > 0 )
{
// create the shell object
IShellDispatch *pShellDispatch = NULL;
HRESULT hr = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void**)&pShellDispatch);
if( SUCCEEDED( hr ) )
{
Folder *pFolder = NULL;
variant_t vaDirectory( lpszDirectoryName );
// get the namespace
if( SUCCEEDED( pShellDispatch->NameSpace( vaDirectory, &pFolder ) ) )
{
FolderItem *pItem = NULL;
bstr_t vaFileName( lpszFileName );
// parse the name
if( SUCCEEDED( pFolder->ParseName( vaFileName, &pItem ) ) )
{
FolderItemVerbs* pVerbs = NULL;
// get the verbs
if( SUCCEEDED( pItem->Verbs(&pVerbs) ) )
{
long nCount = 0;
if( SUCCEEDED ( pVerbs->get_Count( &nCount ) ) )
{
variant_t vaIndex;
vaIndex.vt = VT_I4;
// iterate through verbs
for( vaIndex.lVal = 0; vaIndex.lVal<nCount; vaIndex.lVal++ )
{
FolderItemVerb* pVerb = NULL;
if( SUCCEEDED( pVerbs->Item( vaIndex, &pVerb ) ) )
{
BSTR bstrVerbName = NULL;
// check for 'Pin to Start' verb
if( SUCCEEDED( pVerb->get_Name( &bstrVerbName ) ) )
{
if( 0 == wcscmp( bstrVerbName, szPinToStartLocalized ) )
{
bSuccess = SUCCEEDED( pVerb->DoIt() );
vaIndex.lVal = nCount; // break for
}
::SysFreeString( bstrVerbName );
}
pVerb->Release();
} // if
} // for
}
pVerbs->Release();
}
pItem->Release();
}
pFolder->Release();
}
pShellDispatch->Release();
}
}
::FreeLibrary( hShell32 );
}
return bSuccess;
}
Hope it's help you