How to AES CBC encryption Using cryptoAPI - c++

I want to encrypt a file with AES CBC mode encryption, Using cryptoAPI functions and set my own key from the command-line (It my change in the code)
I imagine that the key (after change) will be 1a1dc91c907325c6 and tried in this form:
HCRYPTPROV hProv = NULL;
HCRYPTKEY hKey = NULL;
DWORD dwBlobLen;
PBYTE pbKeyBlob = NULL;
pbKeyBlob = (PBYTE)"1a1dc91c907325c6";
if(!CryptAcquireContext(&hProv, NULL,NULL, PROV_RSA_AES,CRYPT_VERIFYCONTEXT))
{
printf(" Error in AcquireContext 0x%08x \n",GetLastError());
}
if (!CryptImportKey(hProv,pbKeyBlob,sizeof(pbKeyBlob),0,CRYPT_EXPORTABLE,&hKey ))
{
printf("Error 0x%08x in importing the Des key \n",GetLastError());
}
but CryptImportKey failed
I don't know how to use cryptoAPI functions and It's parameters
I tested some other codes and change the parameters or function's call's order for about 2 weeks but I wasn't able to do this
Please help me [a big help :)]
Thank you

You should do it like this:
if( ::CryptAcquireContext( &m_hCryptoProvider, NULL, NULL/*Default*/, PROV_RSA_AES, CRYPT_VERIFYCONTEXT ) )
{
//Hash Password
// CALG_SHA1 OK
// CALG_AES_128 / CALG_AES_256 => error
if( ::CryptCreateHash( m_hCryptoProvider, CALG_SHA1, 0, 0, &m_hHashPassword ) )
{
// Hash for the password.
if( ::CryptHashData( m_hHashPassword, (BYTE *)password, (DWORD) _tcslen(password) * sizeof(TCHAR), 0 ) )
{
// Session key from the hash
if( ::CryptDeriveKey( m_hCryptoProvider, CALG_AES_256, m_hHashPassword, CRYPT_CREATE_SALT, &m_hCryptKey ) )
{
TRACE( TEXT("Crypto-API OK\n") );
return ERROR_SUCCESS;
}
else
{
TRACE( TEXT("Error in CryptDeriveKey\n") );
}
}
else
{
TRACE( TEXT("Error in CryptHashData\n") );
}
}
else
{
TRACE( TEXT("Error in CryptCreateHash\n") );
}
}
else
{
TRACE( TEXT("Error in CryptAcquireContext\n") );
}
After that you need to use CryptEncrypt/CryptDecrypt to do encode/decode data.

Related

Programmatically pair bluetooth device as audio device

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, &regHandle, (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, &regHandle, (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 to determinate if my application is running under SYSTEM account or not?

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?

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;
}

Windows 8 mapped drives paths not recognized correctly by Service

I am facing a problem in Windows 8 where an elevated application/service that impersonates the logged in user does not recognize the mapped drives paths correctly.
I have a windows service that I use to copy files from/to different source paths/destinations including mapped network drives. The Paths are fed to the service through an xml file. The service then reads the source and destination from the xml and copies the file. I never had an issue with mapped drives in Vista and 7 as the service always impersonates the logged user by getting the explorer token and all my CreateFile, ReadFiles and WriteFile worked perfectly.
This is how I impersonate the user
first I get the session token using the following code
DWORD GetActiveSessionId(DWORD& ret)
{
ret=0;
DWORD active_session_id = WTSGetActiveConsoleSessionId();
if (IsSessionActive(active_session_id))
{
return active_session_id;
}
DWORD console_session_ID = active_session_id;
active_session_id = -2;
WTS_SESSION_INFO* session_info = NULL;
DWORD num_sessions = 0;
if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1,
&session_info, &num_sessions))
{
// Pick the first active session we can find
for (DWORD i = 0 ; i < num_sessions; ++i)
{
if (session_info[i].State == WTSActive)
{
// There is a user logged on to the WinStation associated with the
// session.
active_session_id = session_info[i].SessionId;
break;
}
}
WTSFreeMemory(session_info);
return active_session_id;
}
ret=::GetLastError();
return -2;
}
BOOL GetSessionUserToken( HANDLE * phUserToken, DWORD& retCode )
{
if( NULL == phUserToken )
{
return FALSE;
}
BOOL bRet = FALSE;
HANDLE hImpersonationToken = NULL;
BOOL bWin2K = FALSE;
OSVERSIONINFOEX osv;
ZeroMemory( & osv, sizeof( OSVERSIONINFOEX ) );
osv.dwOSVersionInfoSize = sizeof( OSVERSIONINFOEX );
if( GetVersionEx( (OSVERSIONINFO*) & osv ) )
{
if( 0 == osv.dwMinorVersion && osv.dwMajorVersion == 5)
{
return FALSE;
}
}
DWORD dwActiveSession= CGSSystem::GetActiveSessionId(retCode);
if (dwActiveSession==GSInvalidSessionId)
return FALSE;
if( 0 != WTSQueryUserToken( dwActiveSession, & hImpersonationToken ) )
{
bRet = TRUE;
}
else
{
}
DWORD neededSize = 0;
HANDLE *realToken = new HANDLE;
if(GetTokenInformation(hImpersonationToken, (::TOKEN_INFORMATION_CLASS) TokenLinkedToken, realToken, sizeof(HANDLE), &neededSize))
{
CloseHandle(hImpersonationToken);
hImpersonationToken = *realToken;
}
DWORD lastError = GetLastError();
delete realToken;
if( TRUE == bRet )
{
bRet = DuplicateTokenEx( hImpersonationToken,
0,
NULL,
SecurityImpersonation,
TokenPrimary,
phUserToken );
CloseHandle( hImpersonationToken );
}
return bRet;
}
Then I have my CopyFile function which is a thread. It is a huge function so I will only mention the important (impersonation/security) parts.
BOOL CopyFile(LPCTSTR source, LPCTSTR destination)
{
//Some variables initializations
//...
HRESULT hrInternal = CoInitializeSecurity(
NULL, // Allow *all* VSS writers to communicate back!
-1, // Default COM authentication service
NULL, // Default COM authorization service
NULL, // reserved parameter
RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // Strongest COM authentication level
RPC_C_IMP_LEVEL_IDENTIFY, // Minimal impersonation abilities
NULL, // Default COM authentication settings
EOAC_NONE, // No special options
NULL // Reserved parameter
);
//Initialize security descriptors
SECURITY_DESCRIPTOR SD;
SECURITY_ATTRIBUTES copyMutexAttrib;
copyMutexAttrib.nLength = sizeof( SECURITY_ATTRIBUTES );
copyMutexAttrib.lpSecurityDescriptor = & SD;
copyMutexAttrib.bInheritHandle = TRUE;
if(!InitializeSecurityDescriptor( & SD, SECURITY_DESCRIPTOR_REVISION ) )
{
//Error handling;
}
// add a NULL disc. ACL to the security descriptor.
//
if( ! SetSecurityDescriptorDacl( & SD, TRUE, (PACL) NULL, FALSE ) )
{
//Error handling;
}
HRESULT hr=S_OK;
hr=ModifyThreadPrivilege( SE_BACKUP_NAME, TRUE , m_hUserToken==NULL ? FALSE : TRUE );
if (FAILED(hr))
{
//Error Handling and logs
}
hr=S_OK;
hr=ModifyThreadPrivilege( SE_TCB_NAME, TRUE , m_hUserToken==NULL ? FALSE : TRUE );
if (FAILED(hr))
{
//Error Handling and logs
}
hr=ModifyThreadPrivilege( SE_IMPERSONATE_NAME, TRUE , m_hUserToken==NULL ? FALSE : TRUE );
if (FAILED(hr))
{
//Error Handling and logs
}
hr=ModifyThreadPrivilege( SE_MANAGE_VOLUME_NAME, TRUE , m_hUserToken==NULL ? FALSE : TRUE );
if (FAILED(hr))
{
//Error Handling and logs
}
hr=ModifyThreadPrivilege( SE_SYSTEM_PROFILE_NAME, TRUE , m_hUserToken==NULL ? FALSE : TRUE );
if (FAILED(hr))
{
//Error Handling and logs
}
hr=ModifyThreadPrivilege( SE_DEBUG_NAME, TRUE , m_hUserToken==NULL ? FALSE : TRUE );
if (FAILED(hr))
{
//Error Handling and logs
}
//Other variable initializations
//...
//Create the destination file
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
HANDLE hFile = ::CreateFile(destination, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, &sa,
CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH|FILE_FLAG_BACKUP_SEMANTICS, NULL); //---> creates the file in the wrong location
}
and this is my ModifyThreadPrivilage code:
HRESULT ModifyThreadPrivilege(IN LPCTSTR szPrivilege,IN BOOL fEnable,IN BOOL OpenAsSelf)
{
HRESULT hr = S_OK;
TOKEN_PRIVILEGES NewState;
LUID luid;
HANDLE hToken = NULL;
// Open the process token for this process.
if (!OpenThreadToken(GetCurrentThread(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
OpenAsSelf,
&hToken ))
{
int iLast=::GetLastError();
if (iLast != ERROR_NO_TOKEN)
{
return ERROR_FUNCTION_FAILED;
}
/*
* No access token for the thread so impersonate the security context
* of the process.
*/
if (!ImpersonateSelf(SecurityImpersonation))
{
return ERROR_FUNCTION_FAILED;
}
if (!OpenThreadToken(GetCurrentThread(),
TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
FALSE,
&hToken))
{
return ERROR_FUNCTION_FAILED;
}
}
// Get the local unique ID for the privilege.
if ( !LookupPrivilegeValue( NULL,
szPrivilege,
&luid ))
{
CloseHandle( hToken );
printf("Failed LookupPrivilegeValue\n");
return ERROR_FUNCTION_FAILED;
}
// Assign values to the TOKEN_PRIVILEGE structure.
NewState.PrivilegeCount = 1;
NewState.Privileges[0].Luid = luid;
NewState.Privileges[0].Attributes =
(fEnable ? SE_PRIVILEGE_ENABLED : 0);
// Adjust the token privilege.
if (!AdjustTokenPrivileges(hToken,
FALSE,
&NewState,
0,
NULL,
NULL))
{
hr = ERROR_FUNCTION_FAILED;
}
// Close the handle.
CloseHandle(hToken);
return hr;
}
In windows 8 and when the destination is a mapped drive like "Z:\MyFile.txt" it writes the file to the wrong location like so:
I have mapped network drive Z: which is mapped to
\\nsa\public\myfolder1\subfolder\ the function writes the file to
\\nsa\public\
I have never had such behavior in Windows Vista or 7 but it seems that MS has introduced some new privileges or securities that are causing such behavior.
I have noticed many people complaining about mapped drives in Windows 8, especially for elevated processes but all the solutions suggest to use UNC paths instead of the mapped drive letter.
I also noticed that enabling/disabling UAC has no effect on this.
Can someone explain how can I achieve my goal in copying the file?

Read Epson Printer Status using C++ and ESC/P

I'm trying to get the status of a PLQ-20 Espon printer, using C++, but with no success.
I tried that using GDI API and Escape function with PASSTHROUGH parameter, but the printer never understands the escape codes with that function.
I tried to use WIN 32 API and the example code found here. That works for sending some escape codes like BEL (to sound the buzzer) or FF (Form Feed, to eject paper from the rear of the printer), but not ESC O (to eject paper from the front of the printer), ESC 0 / ESC 1 (to initialize the printer / reset errors).
So, I tried this way to get the status of the printer with a ESC j escape code but with no success (the ReadPrinter function returns 0). Moreover, the print buffer seems to be not empty nonetheless I only send escape commands.
I don't know if I do a mistake sending escape codes or trying to read the printer status.
If anyone could post examples, it could be fine for everyone because it's hard to find them on the web.
Below is the code I use to send commands and read the result
#include <Windows.h>
#include <StdIO.h>
// **********************************************************************
// PrintError - uses printf() to display error code information
//
// Params:
// dwError - the error code, usually from GetLastError()
// lpString - some caller-defined text to print with the error info
//
// Returns: void
//
void PrintError( DWORD dwError, LPCTSTR lpString )
{
#define MAX_MSG_BUF_SIZE 512
TCHAR *msgBuf;
DWORD cMsgLen;
cMsgLen = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_ALLOCATE_BUFFER | 40, NULL, dwError,
MAKELANGID(0, SUBLANG_ENGLISH_US), (LPTSTR) &msgBuf,
MAX_MSG_BUF_SIZE, NULL );
printf("%s Error [%d]:: %s\n", lpString, dwError, msgBuf );
LocalFree( msgBuf );
#undef MAX_MSG_BUF_SIZE
}
// end PrintError
// **********************************************************************
// **********************************************************************
// ReadFileWithAlloc - allocates memory for and reads contents of a file
//
// Params:
// szFileName - NULL terminated string specifying file name
// pdwSize - address of variable to receive file bytes size
// ppBytes - address of pointer which will be allocated and contain file bytes
//
// Returns: TRUE for success, FALSE for failure.
//
// Notes: Caller is responsible for freeing the memory using GlobalFree()
//
BOOL ReadFileWithAlloc( LPTSTR szFileName, LPDWORD pdwSize, LPBYTE *ppBytes )
{
HANDLE hFile;
DWORD dwBytes;
BOOL bSuccess = FALSE;
// Validate pointer parameters
if( ( pdwSize == NULL ) || ( ppBytes == NULL ) )
return FALSE;
// Open the file for reading
hFile = CreateFile( szFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile == INVALID_HANDLE_VALUE )
{
PrintError( GetLastError(), TEXT("CreateFile()") );
return FALSE;
}
// How big is the file?
*pdwSize = GetFileSize( hFile, NULL );
if( *pdwSize == (DWORD)-1 )
PrintError( GetLastError(), TEXT("GetFileSize()") );
else
{
// Allocate the memory
*ppBytes = (LPBYTE)GlobalAlloc( GPTR, *pdwSize );
if( *ppBytes == NULL )
PrintError( GetLastError(), TEXT("Failed to allocate memory\n") );
else
{
// Read the file into the newly allocated memory
bSuccess = ReadFile( hFile, *ppBytes, *pdwSize, &dwBytes, NULL );
if( ! bSuccess )
PrintError( GetLastError(), TEXT("ReadFile()") );
}
}
// Clean up
CloseHandle( hFile );
return bSuccess;
}
// End ReadFileWithAlloc
// **********************************************************************
// **********************************************************************
// RawDataToPrinter - sends binary data directly to a printer
//
// Params:
// szPrinterName - NULL terminated string specifying printer name
// lpData - Pointer to raw data bytes
// dwCount - Length of lpData in bytes
//
// Returns: TRUE for success, FALSE for failure.
//
BOOL RawDataToPrinter( LPTSTR szPrinterName, LPBYTE lpData, DWORD dwCount )
{
HANDLE hPrinter;
DOC_INFO_1 DocInfo;
DWORD dwJob;
DWORD dwBytesWritten;
// Need a handle to the printer.
if( ! OpenPrinter( szPrinterName, &hPrinter, NULL ) )
{
PrintError( GetLastError(), TEXT("OpenPrinter") );
return FALSE;
}
// Fill in the structure with info about this "document."
DocInfo.pDocName = TEXT("My Document");
DocInfo.pOutputFile = NULL;
DocInfo.pDatatype = TEXT("RAW");
// Inform the spooler the document is beginning.
if( (dwJob = StartDocPrinter( hPrinter, 1, (LPBYTE)&DocInfo )) == 0 )
{
PrintError( GetLastError(), TEXT("StartDocPrinter") );
ClosePrinter( hPrinter );
return FALSE;
}
// Start a page.
if( ! StartPagePrinter( hPrinter ) )
{
PrintError( GetLastError(), TEXT("StartPagePrinter") );
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}
// Send the data to the printer.
if( ! WritePrinter( hPrinter, lpData, dwCount, &dwBytesWritten ) )
{
PrintError( GetLastError(), TEXT("WritePrinter") );
EndPagePrinter( hPrinter );
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}
/*********************************/
// CODE USED TO READ THE PRINTER
LPBYTE retData = NULL;
LPDWORD bbr = NULL;
if(ReadPrinter(hPrinter, retData, 1, bbr))
{
printf("OUT : %i", retData);
}
else
{
printf("Failed to read printer");
}
/*********************************/
// End the page.
if( ! EndPagePrinter( hPrinter ) )
{
PrintError( GetLastError(), TEXT("EndPagePrinter") );
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}
// Inform the spooler that the document is ending.
if( ! EndDocPrinter( hPrinter ) )
{
PrintError( GetLastError(), TEXT("EndDocPrinter") );
ClosePrinter( hPrinter );
return FALSE;
}
// Tidy up the printer handle.
ClosePrinter( hPrinter );
// Check to see if correct number of bytes were written.
if( dwBytesWritten != dwCount )
{
//printf( TEXT("Wrote %d bytes instead of requested %d bytes.\n"), dwBytesWritten, dwCount );
return FALSE;
}
return TRUE;
}
// End RawDataToPrinter
// **********************************************************************
int main( int argc, char* argv[] )
{
LPBYTE pBytes = NULL;
int textSize = 2;
DWORD dwSize = textSize;
pBytes = (LPBYTE) malloc (textSize*sizeof(BYTE));
pBytes[0] = 0x1B;
pBytes[1] = 0x6A;
if( ! RawDataToPrinter(L"EPSON PLQ-20 ESC/P2", pBytes, dwSize) )
printf("Failed to send data to printer.\n" );
else
printf("Data sent to printer.\n" );
free(pBytes);
return 0;
}
// end main
// **********************************************************************
Thanks!
The product brochure for the Epson PLQ-20, states that printer supports Olivetti PR2E, Epson ESC/P2, Wincor 4915, IBM PPDS, IBM 4722 FP emulation.
It looks like you are using ESC/P2 commands, however after a quick search I cannot find any command to read the current status of the printer.
ESC/P2 References
http://www.pcguru.plus.com/escp2.html
Complete Manual
http://gimp-print.sourceforge.net/developer-html/c464.html
Based on the above references, the command that controls how the paper is ejected is ESC EM