Related
I have some problem In the RIL program when I try to get the whole Message...
this is a pointer to Array of Byte..passed to hexdump function..
prmMsg->msgInDeliver.rgbMsg
prmMsg is a RILMESSAGE structure..
If the body of the message is only one char I can read that char...
otherwise no!!
Can anyone Help me??
TCHAR *hexdump(unsigned char *data, int n)
{
static TCHAR buf[1000];
TCHAR *p;
p=buf;
while (n--)
{
p += _sntprintf(p, 4, TEXT("%c"), *data);
}
return buf;
}
Anyone have any Idea???????
Please......
I have the same problem Mister lollone,
I'm not able to read message...
when I shift array ..I read a random part of a memory..
but I cannot read the right sequence of char..
I don't know if anyone have accomplish that..
I don't know why the second and third byte are shifted..
at the first was added 1 bit ....
BYTE rgbMsg[MAXLENGTH_MSG];
why???
anyone know the solution....it's impossible!!!
RILMESSAGE
I have the same problem.......HELP US (qtek8080)
Maybe the problem is caused by Unicode. SMS messages can be sent using Unicode. Because it is double byte, treating it as a standard null terminated string would terminate after the first byte because it would encounter a null byte next.
Solution
Here the solution on how to read SMS:
TCHAR *hexdump(unsigned char *data, int n)
{
static TCHAR buf[1000];
unsigned char use=0;
unsigned char add=0;
unsigned char step=7;
unsigned char lo=0;
char tmp;
unsigned char shdgt=255;
int bpow=0;
unsigned char badd=0;
int pi=0;
int dt=0;
int dgt=0;
while (n--)
{
use = data[dt];
if ( step == 7 ) {
shdgt = shdgt >> 1;
lo = use & shdgt;
tmp= lo;
}
else {
shdgt = shdgt >> 1;
lo = use & shdgt;
tmp = lo << (7 - step);
tmp = tmp | add;
}
// get the digit that have to be used in the next char
dgt = 0;
add = 0;
for (int i=step; i<8; i++) {
bpow = pow(2,i);
badd = pow(2,dgt);
if ( use & bpow)
add = add + badd;
dgt++;
}
buf[pi]=tmp;
pi++;
if ( step == 1 ){
// have an extra char to write
buf[pi]=add;
// reset variables
add = 0;
step= 7;
shdgt=255;
pi++;
}
else
{
step--;
}
dt++;
}
return buf;
}
:wink: :wink:
Grazie mille ora lo proverò
OK i am a begginer at programming in eVC++ i would like to create an application like urs but i dont seem to be able to make it work, i'm a great programmer but eVC++ is bad for me.
Could somebody please post a working source code cos i have serious problems and it is critical for me to get a hold on this kind of source code to help me understand.
Thanks all for ur help !!!!!
Hello,
I have written a DLL on eVC++. And now I want to use this DLL in a .NET program. But by "Add Reference" I got an error, that says:
This is not a .NET assembly.
So my question is, is it possible to using a eVC++ DLL on .NET?
If yes, what should I do, and if not, is there another way to do with this problem?
Thanks all
from http://www.csharphelp.com/archives/archive52.html
Code:
Call Unmanaged Code. Part 1 - Simple DLLImport
By Vyacheslav Biktagirov
Managed world is beautiful, I have all classes I want in FrameWork.. But what if I want call some unmanaged code? For instance, I have DLL written in C++, and want use it from C#.
Let's look some code. Our DLL exports some function, in CDecl convention, that sums two integers:
extern "C" __declspec(dllexport) __cdecl int sum(int a,int b);
And, of course, we want reuse this code in C#. We must recall, that it is no "direct" way to call unmanaged code, but we must inform the compiler, what we want to call, how, and where is needed code located.
[DllImport("TestDll.dll", EntryPoint="sum",
ExactSpelling=false,CallingConvention=CallingConvention.Cdecl)]
static extern int sum(int a,int b);
and now we can call it like normal C# function.
x=5;
y=7;
z=sum(x,y); // x will receive 12
Here is full C# client code - tested for Beta2.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
namespace WindowsApplication6
{
///
/// Summary description for Form1.
///
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button button1;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox textBox2;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox textBox3;
///
/// Required designer variable.
///
private System.ComponentModel.Container components = null;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
///
/// Clean up any resources being used.
///
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.textBox1 = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.textBox2 = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.textBox3 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(64, 192);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(144, 64);
this.button1.TabIndex = 0;
this.button1.Text = "call sum";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(40, 120);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(72, 22);
this.textBox1.TabIndex = 1;
this.textBox1.Text = "2";
//
// label1
//
this.label1.Location = new System.Drawing.Point(128, 128);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(16, 16);
this.label1.TabIndex = 2;
this.label1.Text = "+";
//
// textBox2
//
this.textBox2.Location = new System.Drawing.Point(152, 120);
this.textBox2.Name = "textBox2";
this.textBox2.Size = new System.Drawing.Size(56, 22);
this.textBox2.TabIndex = 3;
this.textBox2.Text = "3";
//
// label2
//
this.label2.Location = new System.Drawing.Point(224, 120);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(24, 23);
this.label2.TabIndex = 4;
this.label2.Text = "=";
//
// textBox3
//
this.textBox3.Location = new System.Drawing.Point(248, 120);
this.textBox3.Name = "textBox3";
this.textBox3.Size = new System.Drawing.Size(112, 22);
this.textBox3.TabIndex = 5;
this.textBox3.Text = "5";
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 15);
this.ClientSize = new System.Drawing.Size(576, 322);
this.Controls.AddRange(new System.Windows.Forms.Control[] {this.textBox3,this.label2,this.textBox2,this.label1,this.textBox1,this.button1});
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
///
/// The main entry point for the application.
///
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
#region My Code
#region Dll Imports
[DllImport("TestDll.dll", EntryPoint="sum",
ExactSpelling=false,CallingConvention=CallingConvention.Cdecl)]
static extern int sum(int a,int b);
#endregion
#region Button Click Events
private void button1_Click(object sender, System.EventArgs e)
{
textBox3.Text=(int.Parse(textBox1.Text)+int.Parse(textBox2.Text)).ToString();
}
#endregion
#endregion
}
}
It sounds very simple, becouse "int" is isomorphic type, says, int in C# and ind C++ is identical. What we can do, when we want operate non-isomorhic types, like String? Recall, that .NET string is some Class, while C++ string is char*,or wchar_t*,or BSTR, .. String may be embedded in a structure, or pointed by pointer, or even something more exotic. Let's call some string function.
[DllImport("Advapi32.dll", EntryPoint="GetUserName", ExactSpelling=false,
SetLastError=true)]
static extern bool GetUserName(
[MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer,
[MarshalAs(UnmanagedType.LPArray)] Int32[] nSize );
This function receives two parameters: char* and int*. Becouse we must allocate char* buffer and receive string by pointer, we can't use UnmanagedType.LPStr attribute, so we pass ANSI string as byte array. int* is more simple-it's 1-element Int32 array. Let's call it:
private void button2_Click(object sender, System.EventArgs e)
{
byte[] str=new byte[20];
Int32[] len=new Int32[1];
len[0]=20;
GetUserName(str,len);
MessageBox.Show(System.Text.Encoding.ASCII.GetString(str));
}
We allocate 20 bytes for receiving ANSI string,one element in Int32 array, set 20 as max string length and call it. For receiving string from byte array I used Text.Encoding.ASCII class.
I am presently writing a RegEdit program to run on my PC and allow editing of the registry on the connected PPC. I have got to the point where I can read the entire registry and I am now implementing function to update the registry i.e. insert new key, delete key, add new Key Values etc...
The problem I have at the moment is trying to add a new value to an existing key. The function I have written so far to do this is as follows, but the call to CeRegSetValueEx(...) returns an error code 5!
Code:
//-----------------------------------------------------------------------------------
// Adds a new key value into the registry.
// // TO DO - add the data
int CRegEditDoc::AddNewKeyValue(HTREEITEM hParent, HKEY hRoot, LPTSTR lpszKey, LPTSTR lpszValueName, DWORD dwType)
{
USES_CONVERSION;
int nItem, rc;
HKEY hKey;
LPWSTR lpwszKey = T2W(lpszKey);
LPWSTR lpwszValueName = T2W(lpszValueName);
try
{
if (lstrlen (lpszKey))
{
if (m_rapi.CeRegOpenKeyEx (hRoot, lpwszKey, 0, 0, &hKey) != ERROR_SUCCESS)
{
return 0;
}
}
else
{
hKey = hRoot;
}
CString strValue = "my data";
LPWSTR lpwszData = T2W(strValue);
DWORD length = dim(lpwszData);
nItem = m_pRightView->GetListCtrl().GetItemCount();
if (m_rapi.CeRegSetValueEx(hKey, lpwszValueName, 0, dwType, (LPBYTE)lpwszData, length*2) != ERROR_SUCCESS) // last 2 lpData, szie in bytes of data.
{
HRESULT hResult = m_rapi.CeRapiGetError();
DWORD dwError = m_rapi.CeGetLastError();
return 0;
}
}
catch (CException* e)
{
TCHAR szCause[255];
e->GetErrorMessage(szCause, 255);
CString errorMsg = _T("Error in: CRegEditDoc::AddNewKeyValue: ");
errorMsg += szCause;
AfxMessageBox(errorMsg);
e->Delete();
}
return 1;
}
I would appreciate a little advise on the matter, as this is the first time I have used the RAPI.
Thanks.
Hi VZ800!
The error you're getting is 'access denied'. In WM5 many RAPI functions (including writing to registry) are blocked for security reasons. Your only choice is to use a dll with CeRapiInvoke functions, but it needs to be deployed through a special cab.
You can read about this on msdn.
By the way, the app you're writing already exists, and it has the same problem.
Good luck!
Thanks for the advice. Since my post I have found that my code works for the HKEY_LOCAL_MACHINE, "/Software".
I will investigate the issue you have pointed me to.
Actually, your code should work for the entire HKEY_CLASSES_ROOT as well. MS decided to block only certain 'sensitive' parts of the registry so they can not be corrupted from the outside by malicious software.
If you noticed, MS's own remote registry editor works through DLLs (a ton of them).
Any way, I skimped on words in my first post, since I was writing it on a bus, and while I love my Jamin, writing long text on it is not very enjoyable.
Let me elaborate on CeRapiInvoke:
It's a function you call on the PC side that receives a DLL name and a function name (in that DLL) as parameters and calls that function on the device. It also lets you transfer buffers of data to and from the called function.
It's a great way to communicate with a PPC device without using sockets. You can write the device side DLL to do what ever you wont (like access protected registry) and report back to the PC.
The only drawback is in WM5 this DLL has to be registered and have a 'system' file attribute set. That's why you have to deploy it by cab.
Like I said before it's all in the MSDN.
Hope this helps.
Thanks. I have read the articles (and printed them) about RAPI Restricted Mode Security etc... http://msdn.microsoft.com/library/d...5/html/wce51conRAPIRestrictedModeSecurity.asp and will write a DLL to go on the PPC which will be installed via CAB etc...
I updated the function to add a new value anyway. Rather than calling the RAPI functions for the registry CeRapi... I will call my own functions in my authorised DLL.
Code:
//-----------------------------------------------------------------------------------
// Adds a new key value into the registry.
//
int CRegEditDoc::AddNewKeyValue(HTREEITEM hParent, HKEY hRoot, LPTSTR lpszKey,
LPTSTR lpszValName, DWORD dwDType, LPBYTE lpData)
{
USES_CONVERSION;
HKEY hKey;
LPWSTR lpwszKey = T2W(lpszKey);
LPWSTR lpwszValName = T2W(lpszValName);
DWORD dwDSize = sizeof(lpData);
try
{
if (lstrlen(lpszKey))
{
if (m_rapi.CeRegOpenKeyEx (hRoot, lpwszKey, 0, 0, &hKey) != ERROR_SUCCESS)
{
return 0;
}
}
else
{
hKey = hRoot;
}
// Check if valuename already exists. Should never happen, but just in case.
if (m_rapi.CeRegQueryValueEx(hKey, lpwszValName, 0, &dwDType, NULL, &dwDSize) == ERROR_SUCCESS)
{
AfxMessageBox(_T("Value of this name already exists!"));
return 0;
}
if (m_rapi.CeRegSetValueEx(hKey, lpwszValName, 0, dwDType, lpData, dwDSize) != ERROR_SUCCESS)
{
HRESULT hResult = m_rapi.CeRapiGetError();
DWORD dwError = m_rapi.CeGetLastError();
AfxMessageBox(_T("Unable to create new value for this key!\nPlease check access rights."));
return 0;
}
}
catch (CException* e)
{
TCHAR szCause[255];
e->GetErrorMessage(szCause, 255);
CString errorMsg = _T("Error in: CRegEditDoc::AddNewKeyValue: ");
errorMsg += szCause;
AfxMessageBox(errorMsg);
e->Delete();
}
return 1;
}
A question on using the CeRapiInvoke function. Obviously my function that I will be invoking in my DLL will need to conform to the following footprint:
Code:
LPCWSTR, LPCWSTR, DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream**, DWORD
What I would like to know is this: If I want my function to be a wrapper to say the
Code:
CeRegQueryValueEx(HKEY, LPWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD)
function, how do I parse the function args? Please suggest how I would pack them into a BYTE* for the pInput parameter.
Actually, you got it a bit wrong:
Code:
FuncName(DWORD cbInput, BYTE *pInput, DWORD *pcbOutput, BYTE **ppOutput, IRAPIStream *ppIRAPIStream);
The prototype you specified is for the PC side (the first two strings are DLL name and function name);
I use the following parsing method:
Code:
BYTE* curInputPos = pInput;
memcpy((BYTE*)&hKey, curInputPos, sizeof(HKEY));
curInputPos += sizeof(HKEY);
memcpy((BYTE*)&dwIndex, curInputPos, sizeof(DWORD));
curInputPos += sizeof(DWORD);
memcpy((BYTE*)&Reserved, curInputPos, sizeof(DWORD));
curInputPos += sizeof(DWORD);
It works fine both ways.
Just don't forget to use LocalAlloc for inBuffer and LocalFree for outBuffer.
Thanks. I'll let you know how I get on.
So if I were to parse an HKEY and an LPTSTR accross I would do the following to put the data into a BYTE array:
Code:
DWORD dwIn, dwOut;
LPBYTE pInput;
PDWORD pOut;
dwIn = sizeof(HKEY) + (strlen(lpszKey)*sizeof(TCHAR));
pInput = (BYTE*)(LocalAlloc(LPTR, dwIn));
memcpy(pInput, (BYTE*)&hKey, sizeof(HKEY));
pInput += sizeof(HKEY);
memcpy(pInput, (BYTE*)&lpszKey, strlen(lpszKey)*sizeof(TCHAR));
// move pointer back to begining.
pInput -= sizeof(HKEY);
Basically, yes but with two reservations:
1) I recommend using a different pointer for the current position in buffer, to avoid errors.
2) you need to put the string length in the byte array before the string, otherwise you won't know it's length on the device side. Alternatively, you have to add 1 to the length so the 0 byte at the end gets packed and you can use strlen on the device.
Also keep in mined that unless you define the PC side project to work with UNICODE libraries, THCHAR will be defined as char, while on the device it's always WCHAR.
I really apreciate your help. I still can't get my DLL function to work I keep getting error 1064!
This is my code for the DLL named REditSvr.dll:
Code:
#include <windows.h>
#ifdef __cplusplus
extern "C"
{
#endif
__declspec (dllexport) INT RegEditDeleteValue (DWORD cbInput, BYTE* pInput, DWORD* pcbOutput, BYTE** ppOutput, PVOID reserved);
#ifdef __cplusplus
}
#endif
BOOL WINAPI DllMain (HANDLE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
return TRUE;
}
INT RegEditDeleteValue (DWORD cbInput, BYTE* pInput, DWORD* pcbOutput, BYTE** ppOutput, PVOID reserved)
{
INT rc = 0;
BYTE* curInputPos = pInput;
HKEY hKey;
DWORD dwLength;
// Copy args out of input buffer.
memcpy((BYTE*)&hKey, curInputPos, sizeof(HKEY));
curInputPos += sizeof(HKEY);
memcpy((BYTE*)&dwLength, curInputPos, sizeof(DWORD));
curInputPos += sizeof(DWORD);
// Allocate enough memory for local wchar.
LPWSTR lpszValueName = (WCHAR*)malloc(dwLength);
memcpy((BYTE*)&lpszValueName, curInputPos, sizeof(dwLength));
curInputPos += sizeof(dwLength);
// Do the registry delete.
rc = RegDeleteValue(hKey, lpszValueName);
// Allocate memory for the return buffer.
BYTE* pOutput = (BYTE*)LocalAlloc(LPTR, sizeof(long));
memcpy(pOutput, (BYTE*)rc, sizeof(long));
*ppOutput = pOutput;
*pcbOutput = sizeof(long);
// Free input buffer.
LocalFree(pInput);
// Free WCHAR
free(lpszValueName);
return GetLastError();
}
and this is the code in my PC application which invokes the above function (or I would hope it did):
Code:
//-----------------------------------------------------------------------------------
// Deletes the key value from the registry.
//
int CRegEditDoc::DeleteKeyValue(HKEY hRoot, LPCTSTR lpszKey, LPCTSTR lpszValName)
{
USES_CONVERSION;
HKEY hKey;
LPWSTR lpwszKey = T2W(lpszKey);
LPWSTR lpwszValName = T2W(lpszValName);
try
{
if (lstrlen(lpszKey))
{
if (m_rapi.CeRegOpenKeyEx (hRoot, lpwszKey, 0, 0, &hKey) != ERROR_SUCCESS)
{
return 0;
}
}
else
{
hKey = hRoot;
}
/* if (m_rapi.CeRegDeleteValue(hKey, lpwszValName) != ERROR_SUCCESS)
{
HRESULT hResult = m_rapi.CeRapiGetError();
DWORD dwError = m_rapi.CeGetLastError();
AfxMessageBox(_T("Unable to delete value for this key!\nPlease check access rights."));
return 0;
}
*/
// Testing remote registry value deletion.
DWORD dwIn, dwOut;
LPBYTE pInput, pCurInputPos;
PDWORD pOut;
DWORD dwLength = wcslen(lpwszValName)*sizeof(WCHAR);
dwIn = sizeof(HKEY) + dwLength;
pInput = (BYTE*)(LocalAlloc(LPTR, dwIn));
pCurInputPos = pInput;
memcpy(pCurInputPos, (BYTE*)&hKey, sizeof(HKEY));
pCurInputPos += sizeof(HKEY);
// Store the length of the string
memcpy(pCurInputPos, (BYTE*)&dwLength, sizeof(DWORD));
pCurInputPos += sizeof(DWORD);
memcpy(pCurInputPos, (BYTE*)&lpwszValName, dwLength);
HRESULT hr = m_rapi.CeRapiInvoke(L"REditSvr", L"RegEditDeleteValue", dwIn,
pInput, &dwOut, (PBYTE*)&pOut, NULL, 0);
HRESULT hResult = m_rapi.CeRapiGetError();
DWORD dwError = m_rapi.CeGetLastError();
LocalFree(pOut);
if (hKey != hRoot)
{
m_rapi.CeRegCloseKey(hKey);
}
}
catch (CException* e)
{
TCHAR szCause[255];
e->GetErrorMessage(szCause, 255);
CString errorMsg = _T("Error in: CRegEditDoc::DeleteKeyValue: ");
errorMsg += szCause;
AfxMessageBox(errorMsg);
e->Delete();
}
return 1;
}
The DLL has been deployed to the PPC \Windows folder by eVC4. My PPC runs WM5 (is this the problem, although I have written programs with eVC4 ok for it).
I would again appreciate your help/advice on why this isn't working. At present I have unlocked my PPC and I am able to edit any part of the registry etc...
Hi VZ800!
I noticed a couple of errors in your code (which you may have corrected yourself by now) but the biggest problem, I think is that you don't register the dll.
Here is the part you missed from MSDN:
(full link: http://msdn.microsoft.com/library/d...en-us/mobilesdk5/html/mob5lrfcerapiinvoke.asp)
To satisfy the requirements of the Remote Access Security Policy
1. Create a provisioning XML document that adds the new node "RAPI" to the metabase. This node must include the absolute path to the *.DLL file. For more information, see Metabase Settings. The following code example shows the contents of a typical provisioning XML file.
<wap-provisioningdoc>
<characteristic type="Metabase">
<characteristic type="RAPI\Program Files\Green Sky\recaller.dll\*">
<parm name="rw-access" value="3"/>
<parm name="access-role" value="152"/>
</characteristic>
</characteristic>
</wap-provisioningdoc>
2. Pass the file name of the provisioning XML document to the CAB wizard using the /postxml command line option. The CAB wizard will append the XML to the _setup.xml file it places in the CAB. For more information on creating CAB files, see CAB Wizard.
3. Set the System attribute on the *.DLL file.
Only the Manager security role provides the required permissions for modifying the metabase. The ideal way to get this security role is to have your application signed with a privileged certificate.
Note Since Pocket PC implements a one-tier security model, the CAB install process will automatically have the Manager security role.
Click to expand...
Click to collapse
Here's my advice:
Create a simple function that doesn't receive parameters, but pops up a message on the device. When you see that calling it works, try adding the rest of the code.
Hi
As I understand the DLL does not require code to self- register. Anyway, I can call the DLL function and did as you suggested and put a MessageBox in the function. This displayed fine. My code for the DLL is as follows now:
Code:
#include <windows.h>
#ifdef __cplusplus
extern "C"
{
#endif
__declspec (dllexport) INT RegEditDeleteValue (DWORD cbInput, BYTE* pInput, DWORD* pcbOutput, BYTE** ppOutput, PVOID reserved);
#ifdef __cplusplus
}
#endif
BOOL WINAPI DllMain (HANDLE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
return TRUE;
}
INT RegEditDeleteValue (DWORD cbInput, BYTE* pInput, DWORD* pcbOutput, BYTE** ppOutput, PVOID reserved)
{
DWORD rc = 0;
BYTE* curInputPos = pInput;
LPCWSTR lpszValueName;
HKEY hKey;
int len;
// Copy args out of input buffer.
memcpy((BYTE*)&hKey, curInputPos, sizeof(HKEY));
curInputPos += sizeof(HKEY);
// Size of value name string.
memcpy((BYTE*)&len, curInputPos, sizeof(int));
curInputPos += sizeof(int);
// Value name string.
memcpy((BYTE*)&lpszValueName, curInputPos, sizeof(len));
curInputPos += sizeof(len);
// Do the registry delete.
rc = RegDeleteValue(hKey, lpszValueName);
// Allocate memory for the return buffer.
*ppOutput = (BYTE*)LocalAlloc(LPTR, rc);
memcpy(*ppOutput, (BYTE*)&rc, sizeof(DWORD));
*pcbOutput = sizeof(DWORD);
// Free input buffer.
if (pInput)
LocalFree(pInput);
return GetLastError();
}
and this is the code from which I am calling it:
Code:
//-----------------------------------------------------------------------------------
// Deletes the key value from the registry.
//
int CRegEditDoc::DeleteKeyValue(HKEY hRoot, LPCTSTR lpszKey, LPCTSTR lpszValName)
{
USES_CONVERSION;
HKEY hKey;
LPWSTR lpwszKey = T2W(lpszKey);
LPCWSTR lpwszValName = T2W(lpszValName);
try
{
if (lstrlen(lpszKey))
{
if (m_rapi.CeRegOpenKeyEx (hRoot, lpwszKey, 0, 0, &hKey) != ERROR_SUCCESS)
{
return 0;
}
}
else
{
hKey = hRoot;
}
/* if (m_rapi.CeRegDeleteValue(hKey, lpwszValName) != ERROR_SUCCESS)
{
HRESULT hResult = m_rapi.CeRapiGetError();
DWORD dwError = m_rapi.CeGetLastError();
AfxMessageBox(_T("Unable to delete value for this key!\nPlease check access rights."));
return 0;
}
*/
// Testing remote registry value deletion.
DWORD dwIn, dwOut;
LPBYTE pInput, pCurInputPos;
PDWORD pOut, rc;
int len = wcslen(lpwszValName)*sizeof(WCHAR);
dwIn = sizeof(HKEY) + len;
pInput = (BYTE*)(LocalAlloc(LPTR, dwIn));
pCurInputPos = pInput;
// Store the hKey value in the output buffer.
memcpy(pCurInputPos, (BYTE*)&hKey, sizeof(HKEY));
pCurInputPos += sizeof(HKEY);
// Store the length of the string in the output buffer.
memcpy(pCurInputPos, (BYTE*)&len, sizeof(int));
pCurInputPos += sizeof(int);
// Store the value name string in the output buffer.
memcpy(pCurInputPos, (BYTE*)&lpwszValName, len);
HRESULT hr = m_rapi.CeRapiInvoke(L"REditSvr", L"RegEditDeleteValue", dwIn,
pInput, &dwOut, (PBYTE*)&pOut, NULL, 0);
// HRESULT hr = RapiFuncTest(dwIn, pInput, &dwOut, (PBYTE*)&pOut, NULL);
HRESULT hResult = m_rapi.CeRapiGetError();
DWORD dwError = m_rapi.CeGetLastError();
if (dwOut)
{
memcpy((BYTE*)&rc, pOut, sizeof(DWORD));
}
if (pOut)
{
LocalFree(pOut);
}
if (hKey != hRoot)
{
m_rapi.CeRegCloseKey(hKey);
}
}
catch (CException* e)
{
TCHAR szCause[255];
e->GetErrorMessage(szCause, 255);
CString errorMsg = _T("Error in: CRegEditDoc::DeleteKeyValue: ");
errorMsg += szCause;
AfxMessageBox(errorMsg);
e->Delete();
}
return 1;
}
As you can see in the DeleteKeyValue(...) function I called a test-function just to check that I was retrieving the data out of the pInput buffer ok, which I am.
I signed the DLL with the SDKSamplePrivDeveloper.pfx, added the /postxml via the /postxml switch in the cabwiz and successfully created a CAB file which installs the DLL into the \Windows folder on the PPC. The .inf file is as follows:
Code:
[CEStrings]
InstallDir=%CE2%
AppName="REditSvr"
[Strings]
CompanyName="AHartley"
[Version]
Signature="$Chicago$"
CESignature="$Windows CE$"
Provider=%CompanyName%
[SourceDisksNames.Arm]
1=,"arm files",,C:\eMDevelopment\PPCRegEdit\REditSvr\REL
[SourceDisksFiles.Arm]
REditSvr.dll=1
[Files.ARM]
REditSvr.dll
[DestinationDirs]
Files.Arm=,%InstallDir%
[DefaultInstall.Arm]
CopyFiles=Files.Arm
My PC side code invokes the DLL function return 0 as error code. But the error code returned in the ppOutput buffer is 0x00000057 Dec 87. Which equates to the error message "The parameter is incorrect."! Which must be a param of the RegDeleteValue(...) function, as if I comment this out I don't get any error return values!!
Any odeas?
This is all academic now as I won't be finishing the PPCRegEdit program coz of the Remote Registry Editor tool available in the eVC4 IDE, which I hadn't noticed before, duh. But I would like to know why the function isn't working as required.
You were writing this as a tool? :shock:
If you just asked, people would have told you about the existing reg edit and CeRegEdit witch works through RAPI directly.
Still, it is a nice exercise in coding which I done my self once (for other purposes)
Any way, your error is simple:
Code:
// Value name string.
memcpy((BYTE*)&lpszValueName, curInputPos, sizeof(len));
curInputPos += sizeof(len);
You are parsing it incorrectly.
This is how it should look:
Code:
// Value name string.
memcpy((BYTE*)lpszValueName, curInputPos, len);
curInputPos += len;
and on the PC side:
Code:
memcpy(pCurInputPos, (BYTE*)&lpwszValName, len);
should be:
Code:
memcpy(pCurInputPos, (BYTE*)lpwszValName, len);
once again, no offence but if you just read your code more carefully and use debug prints to check parameters, you won't need anyone's help.
Good luck in future projects.
(whoops, made an error my self while correcting another)
Yes, it is just an exercise.
Thanks for all your help. Sorry for the silly errors, I will try and take more care in future.
Hi.
I was developing an app in which I needed to access some of the build.prop values without accessing root.
After some days finally I found a good & working solution.
So, for whom they need it later, I decided to share it here.
All you have to do is this :
1. Make a process which executes "getprop" from the "/system/bin/getprop" directory and initialize the String which we want to get (ro.board.platform in example).
2. Make a BufferedReader which gets the value (String) by retrieving the data from a inputStreamReader().
3.Convert the BufferedReader to String.
Help your selves.
Code:
Process p = null;
String board_platform = "";
try {
p = new ProcessBuilder("/system/bin/getprop", "ro.board.platform").redirectErrorStream(true).start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line=br.readLine()) != null){
board_platform = line;
}
p.destroy();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Thanks man!.,,..
But are we really in such a need of getprop? If I remember correctly, on all Android devices /system partition is world-readable. So we can just read it build.prop like a normal text file and then parse it.
Dr.Alexander_Breen said:
But are we really in such a need of getprop? If I remember correctly, on all Android devices /system partition is world-readable. So we can just read it build.prop like a normal text file and then parse it.
Click to expand...
Click to collapse
Maybe you're right.
But before the Tut، I collected some info on build.prop.
I read different files from different devices with different ROMs.
And I gained a result : The file differs from ROM to ROM and from device to device.
I had thought of this knowing that in device Nexus 4 "ro.x.y" is in line "z" forexample :
1. Create BufferedReader to read the build.prop file.
2.
// Let's consider ro.x.y : outcome in build.prop
int x = 0;
String y ="";
If ((y = br.readLine()) != null) {
x++;
String line = y;
if (x = z){
// So we have found ro.x.y
String result = line;
result = result.replaceAll("ro.x.y", "");
result = result.replaceAll(" :", "");
}
}
Using this procedure we have retreived the ro.x.y value in Nexus 4.
But does anybody promise that ro.x.y is in line "z" in all devices?
The answer is NO as I mentioned above.
Maybe someone has changed his build.prop file and ... .
I hope it helps.
Shouldn't the title be [Guide], not [Guilde]?
nikwen said:
Shouldn't the title be [Guide], not [Guilde]?
Click to expand...
Click to collapse
Thanks sir.
Didn't notice at all.
And here is C# Translation for the code:
------------------------------------------------------------------------------------------------
Global Variables
------------------------------------------------------------------------------------------------
Code:
private Process p = null;
private string AdbPath = Path.Combine(Path.GetTempPath(), "RegawMOD", "AndroidLib", "adb");
------------------------------------------------------------------------------------------------
Process Definition
------------------------------------------------------------------------------------------------
Code:
try
{
p = new Process();
ProcessStartInfo sInfo = new ProcessStartInfo("cmd");
sInfo.RedirectStandardOutput = true;
sInfo.RedirectStandardInput = true;
sInfo.CreateNoWindow = true;
sInfo.UseShellExecute = false;
sInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo = sInfo;
p.OutputDataReceived += p_OutputDataReceived;
p.EnableRaisingEvents = true;
p.Start();
p.BeginOutputReadLine();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error starting adb process", MessageBoxButton.OK, MessageBoxImage.Error);
}
------------------------------------------------------------------------------------------------
p_OutputDataReceived Definition
------------------------------------------------------------------------------------------------
Code:
void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
string line = "";
try
{
if (!(line = e.Data).Trim().Length.Equals(0) && !line.Contains("/system/bin/getprop ro.board.platform"))
{
this.Dispatcher.BeginInvoke(new Action(() => txt.AppendText(line + "\n")));
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error Reading Output", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
------------------------------------------------------------------------------------------------
Passing command to our little adb process
------------------------------------------------------------------------------------------------
Code:
if (p != null)
{
p.StandardInput.WriteLine(AdbPath + " shell /system/bin/getprop ro.board.platform");
}
------------------------------------------------------------------------------------------------
Side Notes:
------------------------------------------------------------------------------------------------
Code above will result in active shell, it's a simulation for executing commands via CMD
What you need to do is the following:
Change "AdbPath" content to match the path of your adb executable.
"txt" is the Textbox that will show the output, put your own object.
Remove this line " !line.Contains("/system/bin/getprop ro.board.platform);" from "p_OutputDataReceived" to have an idea why I included it in the first place, it's not a must to have it but it will make output look nicer.
In the "Passing command to our little adb process" section, you can replace " shell /system ...etc" with your own object to make the app flexible and be able to execute any command the user type [example: .p.StandardInput.WriteLine(String.Join(" ", AdbPath , CommandTextBox.Text));]
This is almost the same code I execute in Droid Manager for the active shell, I just added few more lines to serve my active shell demands
My device is rooted, nevertheless it doesn't matter which language we are using, as long as we are executing the same command, then it should work with non rooted devices too just like OP says
I use AndroidLib that's why my Adb path points to AndroidLib's adb executable.
------------------------------------------------------------------------------------------------
Good luck
------------------------------------------------------------------------------------------------
Edit:
Dr.Alexander_Breen said:
But are we really in such a need of getprop? If I remember correctly, on all Android devices /system partition is world-readable. So we can just read it build.prop like a normal text file and then parse it.
Click to expand...
Click to collapse
@Dr.Alexander_Breen Yes /system is read only and we can read the file, but if you read it like a text file you will have to break text apart to get the value and not key + value. and you will have to go line by line to reach the key you want, so by using "getprop" you will get the value without having to write extra lines of code to make the app show you value only. As for me I prefer it that way, no need to make the app execute more lines of code just to get a part of the string.
torpedo mohammadi said:
Using this procedure we have retreived the ro.x.y value in Nexus 4.
But does anybody promise that ro.x.y is in line "z" in all devices?
The answer is NO as I mentioned above.
Maybe someone has changed his build.prop file and ... .
I hope it helps.
Click to expand...
Click to collapse
Well, we are supposed to write smart parser which is indifferent to line number, it searches by key name...and gets the value. However, that is the reinvention of the wheel - getprop does exactly the same.
Just saying that the same result is available without the getprop. But it will be (or will not if you're really good in regular expressions) harder, yes.
Alternatively, you can use reflection to access Android's internal android.os.SystemProperties class.
Here is the class I use to reflect it in Pimp My Rom :
Code:
package com.androguide.pimpmyrom.helpers;
import android.content.Context;
import java.io.File;
import java.lang.reflect.Method;
import dalvik.system.DexFile;
/*
Class using reflection to grant access to the private hidden android.os.SystemProperties class
*/
public class SystemPropertiesReflection {
/**
* This class cannot be instantiated
*/
private SystemPropertiesReflection() {
}
/**
* Get the value for the given key.
*
* @return an empty string if the key isn't found
* @Throws IllegalArgumentException if the key exceeds 32 characters
*/
public static String get(Context context, String key) throws IllegalArgumentException {
String ret = "";
try {
ClassLoader cl = context.getClassLoader();
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class[] paramTypes = new Class[1];
paramTypes[0] = String.class;
Method get = SystemProperties.getMethod("get", paramTypes);
//Parameters
Object[] params = new Object[1];
params[0] = new String(key);
ret = (String) get.invoke(SystemProperties, params);
} catch (IllegalArgumentException iAE) {
throw iAE;
} catch (Exception e) {
ret = "";
//TODO
}
return ret;
}
/**
* Get the value for the given key.
*
* [user=2056652]@return[/user] if the key isn't found, return def if it isn't null, or an empty string otherwise
* [user=948141]@Throw[/user]s IllegalArgumentException if the key exceeds 32 characters
*/
public static String get(Context context, String key, String def) throws IllegalArgumentException {
String ret = def;
try {
ClassLoader cl = context.getClassLoader();
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class[] paramTypes = new Class[2];
paramTypes[0] = String.class;
paramTypes[1] = String.class;
Method get = SystemProperties.getMethod("get", paramTypes);
//Parameters
Object[] params = new Object[2];
params[0] = new String(key);
params[1] = new String(def);
ret = (String) get.invoke(SystemProperties, params);
} catch (IllegalArgumentException iAE) {
throw iAE;
} catch (Exception e) {
ret = def;
//TODO
}
return ret;
}
/**
* Get the value for the given key, and return as an integer.
*
* [user=955119]@param[/user] key the key to lookup
* [user=955119]@param[/user] def a default value to return
* [user=2056652]@return[/user] the key parsed as an integer, or def if the key isn't found or
* cannot be parsed
* [user=948141]@Throw[/user]s IllegalArgumentException if the key exceeds 32 characters
*/
public static Integer getInt(Context context, String key, int def) throws IllegalArgumentException {
Integer ret = def;
try {
ClassLoader cl = context.getClassLoader();
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class[] paramTypes = new Class[2];
paramTypes[0] = String.class;
paramTypes[1] = int.class;
Method getInt = SystemProperties.getMethod("getInt", paramTypes);
//Parameters
Object[] params = new Object[2];
params[0] = new String(key);
params[1] = new Integer(def);
ret = (Integer) getInt.invoke(SystemProperties, params);
} catch (IllegalArgumentException iAE) {
throw iAE;
} catch (Exception e) {
ret = def;
//TODO
}
return ret;
}
/**
* Get the value for the given key, and return as a long.
*
* [user=955119]@param[/user] key the key to lookup
* [user=955119]@param[/user] def a default value to return
* [user=2056652]@return[/user] the key parsed as a long, or def if the key isn't found or
* cannot be parsed
* [user=948141]@Throw[/user]s IllegalArgumentException if the key exceeds 32 characters
*/
public static Long getLong(Context context, String key, long def) throws IllegalArgumentException {
Long ret = def;
try {
ClassLoader cl = context.getClassLoader();
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class[] paramTypes = new Class[2];
paramTypes[0] = String.class;
paramTypes[1] = long.class;
Method getLong = SystemProperties.getMethod("getLong", paramTypes);
//Parameters
Object[] params = new Object[2];
params[0] = new String(key);
params[1] = new Long(def);
ret = (Long) getLong.invoke(SystemProperties, params);
} catch (IllegalArgumentException iAE) {
throw iAE;
} catch (Exception e) {
ret = def;
//TODO
}
return ret;
}
/**
* Get the value for the given key, returned as a boolean.
* Values 'n', 'no', '0', 'false' or 'off' are considered false.
* Values 'y', 'yes', '1', 'true' or 'on' are considered true.
* (case insensitive).
* If the key does not exist, or has any other value, then the default
* result is returned.
*
* [user=955119]@param[/user] key the key to lookup
* [user=955119]@param[/user] def a default value to return
* [user=2056652]@return[/user] the key parsed as a boolean, or def if the key isn't found or is
* not able to be parsed as a boolean.
* [user=948141]@Throw[/user]s IllegalArgumentException if the key exceeds 32 characters
*/
public static Boolean getBoolean(Context context, String key, boolean def) throws IllegalArgumentException {
Boolean ret = def;
try {
ClassLoader cl = context.getClassLoader();
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class[] paramTypes = new Class[2];
paramTypes[0] = String.class;
paramTypes[1] = boolean.class;
Method getBoolean = SystemProperties.getMethod("getBoolean", paramTypes);
//Parameters
Object[] params = new Object[2];
params[0] = new String(key);
params[1] = new Boolean(def);
ret = (Boolean) getBoolean.invoke(SystemProperties, params);
} catch (IllegalArgumentException iAE) {
throw iAE;
} catch (Exception e) {
ret = def;
//TODO
}
return ret;
}
/**
* Set the value for the given key.
*
* [user=948141]@Throw[/user]s IllegalArgumentException if the key exceeds 32 characters
* [user=948141]@Throw[/user]s IllegalArgumentException if the value exceeds 92 characters
*/
public static void set(Context context, String key, String val) throws IllegalArgumentException {
try {
[user=1299008]@supp[/user]ressWarnings("unused")
DexFile df = new DexFile(new File("/system/app/Settings.apk"));
[user=1299008]@supp[/user]ressWarnings("unused")
ClassLoader cl = context.getClassLoader();
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class SystemProperties = Class.forName("android.os.SystemProperties");
//Parameters Types
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class[] paramTypes = new Class[2];
paramTypes[0] = String.class;
paramTypes[1] = String.class;
Method set = SystemProperties.getMethod("set", paramTypes);
//Parameters
Object[] params = new Object[2];
params[0] = new String(key);
params[1] = new String(val);
set.invoke(SystemProperties, params);
} catch (IllegalArgumentException iAE) {
throw iAE;
} catch (Exception e) {
//TODO
}
}
}
Then, you can create a static method like the following in order to avoid NPEs if the property we're asking for isn't present and such:
Code:
public static String getSystemProp(Context context, String prop, String default) {
String result = null;
try {
result = SystemPropertiesReflection.get(context, prop);
} catch (IllegalArgumentException iae) {
Log.e(TAG, "Failed to get prop: " + prop);
}
return result == null ? default : result;
}
And simply invoke it to get the returned property, for example:
Code:
String prop = getSystemProp(this, "ro.sf.lcd_density", "213");
EDIT : sorry to the guys that were @ mentionned by the code's annotations
@ whoever's code I decide to use: Thanks, I'll make use of this in my library I'll put you in the credits :good:
I'm using the code in the OP and it's returning the default value, but not the actual value... This is really weird...
EDIT: Ok, so it won't update values until I reboot the device. Is there any workaround?
Tezlastorme said:
EDIT: Ok, so it won't update values until I reboot the device. Is there any workaround?
Click to expand...
Click to collapse
The system properties are not reloaded after you edit the build.prop, you need a reboot, or you've to read from build.prop file.
vektor88 said:
The system properties are not reloaded after you edit the build.prop, you need a reboot, or you've to read from build.prop file.
Click to expand...
Click to collapse
But whenever I read directly from build.prop something screws up, like build.prop becomes empty or deletes itself. In my last test my sdcard became corrupted and build.prop became blank.
Sent from my Galaxy Nexus
Tezlastorme said:
But whenever I read directly from build.prop something screws up, like build.prop becomes empty or deletes itself. In my last test my sdcard became corrupted and build.prop became blank.
Sent from my Galaxy Nexus
Click to expand...
Click to collapse
Use setprop and getprop in addition to the changes you make to the build.prop, this way you can get the current value without the hassle or performance loss of having to parse the whole build.prop for each value you want to read.
For example, if you change ro.whatever=true to ro.whatever=false, also do a setprop ro.whatever false so that you can retrieve the value from getprop ro.whatever
Dr.Alexander_Breen said:
But are we really in such a need of getprop? If I remember correctly, on all Android devices /system partition is world-readable. So we can just read it build.prop like a normal text file and then parse it.
Click to expand...
Click to collapse
If this is true (and i think it is), why <ou don't simply use the Java Properties class to read the prop file?
developer.android.com/reference/java/util/Properties.html
Sorry for answering in this old Thread, but i dont see why you read the properties file by yourself.
amfa84 said:
If this is true (and i think it is), why <ou don't simply use the Java Properties class to read the prop file?
developer.android.com/reference/java/util/Properties.html
Sorry for answering in this old Thread, but i dont see why you read the properties file by yourself.
Click to expand...
Click to collapse
Yeah, it should work, in theory.. But in practice it screw things up a lot. It ends up deleting the whole contents of build.prop or not reading correctly and it's very unpredictable :-/
And yes I was using the Properties class (and still do)
Sent from my sushi grade tuna
---------- Post added at 08:48 AM ---------- Previous post was at 08:47 AM ----------
Androguide.fr said:
Use setprop and getprop in addition to the changes you make to the build.prop, this way you can get the current value without the hassle or performance loss of having to parse the whole build.prop for each value you want to read.
For example, if you change ro.whatever=true to ro.whatever=false, also do a setprop ro.whatever false so that you can retrieve the value from getprop ro.whatever
Click to expand...
Click to collapse
Btw I tried this ^^ and it didn't work
Sent from my sushi grade tuna
Tezlastorme said:
Yeah, it should work, in theory.. But in practice it screw things up a lot. It ends up deleting the whole contents of build.prop or not reading correctly and it's very unpredictable :-/
And yes I was using the Properties class (and still do)
Sent from my sushi grade tuna
---------- Post added at 08:48 AM ---------- Previous post was at 08:47 AM ----------
Btw I tried this ^^ and it didn't work
Sent from my sushi grade tuna
Click to expand...
Click to collapse
Then you're not doing it right, it does work, and it's very easy to test, just open Terminal emulator, and try the following:
Code:
setprop ro.test.prop true
getprop ro.test.prop
# returns
true
As I said, this will not modify the build.prop, but if everytime you modify the build.prop you also use setprop, then you can avoir the big performance overhead of having to parse the whole build.prop just to get the value of a single prop.
The best way to me remains accessing the private android.os.SystemProperties class through reflection. I believe I had already posted the class in this thread earlier, but here it is:
PHP:
package com.androguide.pimpmyromv2.helpers;
import android.content.Context;
import java.io.File;
import java.lang.reflect.Method;
import dalvik.system.DexFile;
/**
* Class using reflection to grant access to the private hidden android.os.SystemProperties class
*/
public class SystemPropertiesReflection {
/**
* This class cannot be instantiated
*/
private SystemPropertiesReflection() {
}
/**
* Get the value for the given key.
*
* @return an empty string if the key isn't found
* @throws IllegalArgumentException if the key exceeds 32 characters
*/
public static String get(Context context, String key) throws IllegalArgumentException {
String ret = "";
try {
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes = new Class[1];
paramTypes[0] = String.class;
Method get = SystemProperties.getMethod("get", paramTypes);
//Parameters
Object[] params = new Object[1];
params[0] = new String(key);
ret = (String) get.invoke(SystemProperties, params);
} catch (IllegalArgumentException iAE) {
throw iAE;
} catch (Exception e) {
ret = "";
//TODO
}
return ret;
}
/**
* Get the value for the given key.
*
* @return if the key isn't found, return def if it isn't null, or an empty string otherwise
* @throws IllegalArgumentException if the key exceeds 32 characters
*/
public static String get(Context context, String key, String def) throws IllegalArgumentException {
String ret = def;
try {
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes = new Class[2];
paramTypes[0] = String.class;
paramTypes[1] = String.class;
Method get = SystemProperties.getMethod("get", paramTypes);
//Parameters
Object[] params = new Object[2];
params[0] = new String(key);
params[1] = new String(def);
ret = (String) get.invoke(SystemProperties, params);
} catch (IllegalArgumentException iAE) {
throw iAE;
} catch (Exception e) {
ret = def;
//TODO
}
return ret;
}
/**
* Get the value for the given key, and return as an integer.
*
* @param key the key to lookup
* @param def a default value to return
* @return the key parsed as an integer, or def if the key isn't found or
* cannot be parsed
* @throws IllegalArgumentException if the key exceeds 32 characters
*/
public static Integer getInt(Context context, String key, int def) throws IllegalArgumentException {
Integer ret = def;
try {
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes = new Class[2];
paramTypes[0] = String.class;
paramTypes[1] = int.class;
Method getInt = SystemProperties.getMethod("getInt", paramTypes);
//Parameters
Object[] params = new Object[2];
params[0] = new String(key);
params[1] = new Integer(def);
ret = (Integer) getInt.invoke(SystemProperties, params);
} catch (IllegalArgumentException iAE) {
throw iAE;
} catch (Exception e) {
ret = def;
//TODO
}
return ret;
}
/**
* Get the value for the given key, and return as a long.
*
* @param key the key to lookup
* @param def a default value to return
* @return the key parsed as a long, or def if the key isn't found or
* cannot be parsed
* @throws IllegalArgumentException if the key exceeds 32 characters
*/
public static Long getLong(Context context, String key, long def) throws IllegalArgumentException {
Long ret = def;
try {
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes = new Class[2];
paramTypes[0] = String.class;
paramTypes[1] = long.class;
Method getLong = SystemProperties.getMethod("getLong", paramTypes);
//Parameters
Object[] params = new Object[2];
params[0] = new String(key);
params[1] = new Long(def);
ret = (Long) getLong.invoke(SystemProperties, params);
} catch (IllegalArgumentException iAE) {
throw iAE;
} catch (Exception e) {
ret = def;
//TODO
}
return ret;
}
/**
* Get the value for the given key, returned as a boolean.
* Values 'n', 'no', '0', 'false' or 'off' are considered false.
* Values 'y', 'yes', '1', 'true' or 'on' are considered true.
* (case insensitive).
* If the key does not exist, or has any other value, then the default
* result is returned.
*
* @param key the key to lookup
* @param def a default value to return
* @return the key parsed as a boolean, or def if the key isn't found or is
* not able to be parsed as a boolean.
* @throws IllegalArgumentException if the key exceeds 32 characters
*/
public static Boolean getBoolean(Context context, String key, boolean def) throws IllegalArgumentException {
Boolean ret = def;
try {
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes = new Class[2];
paramTypes[0] = String.class;
paramTypes[1] = boolean.class;
Method getBoolean = SystemProperties.getMethod("getBoolean", paramTypes);
//Parameters
Object[] params = new Object[2];
params[0] = new String(key);
params[1] = new Boolean(def);
ret = (Boolean) getBoolean.invoke(SystemProperties, params);
} catch (IllegalArgumentException iAE) {
throw iAE;
} catch (Exception e) {
ret = def;
//TODO
}
return ret;
}
/**
* Set the value for the given key.
*
* @throws IllegalArgumentException if the key exceeds 32 characters
* @throws IllegalArgumentException if the value exceeds 92 characters
*/
public static void set(Context context, String key, String val) throws IllegalArgumentException {
try {
@SuppressWarnings("unused")
DexFile df = new DexFile(new File("/system/app/Settings.apk"));
@SuppressWarnings("unused")
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class SystemProperties = Class.forName("android.os.SystemProperties");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes = new Class[2];
paramTypes[0] = String.class;
paramTypes[1] = String.class;
Method set = SystemProperties.getMethod("set", paramTypes);
//Parameters
Object[] params = new Object[2];
params[0] = new String(key);
params[1] = new String(val);
set.invoke(SystemProperties, params);
} catch (IllegalArgumentException iAE) {
throw iAE;
} catch (Exception e) {
//TODO
}
}
}
one x new in android
torpedo mohammadi said:
Hi.
I was developing an app in which I needed to access some of the build.prop values without accessing root.
After some days finally I found a good & working solution.
So, for whom they need it later, I decided to share it here.
All you have to do is this :
1. Make a process which executes "getprop" from the "/system/bin/getprop" directory and initialize the String which we want to get (ro.board.platform in example).
2. Make a BufferedReader which gets the value (String) by retrieving the data from a inputStreamReader().
3.Convert the BufferedReader to String.
Help your selves.
Code:
Process p = null;
String board_platform = "";
try {
p = new ProcessBuilder("/system/bin/getprop", "ro.board.platform").redirectErrorStream(true).start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line=br.readLine()) != null){
board_platform = line;
}
p.destroy();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Click to expand...
Click to collapse
Hi, Is anyone nood friendly to explain me or some tutorial where and how to put this comand, to change my build.prop without unlocking bootloader on my HOX tegra 3..grateful for any response
---------- Post added at 01:25 PM ---------- Previous post was at 01:13 PM ----------
torpedo mohammadi said:
Hi.
I was developing an app in which I needed to access some of the build.prop values without accessing root.
After some days finally I found a good & working solution.
So, for whom they need it later, I decided to share it here.
All you have to do is this :
1. Make a process which executes "getprop" from the "/system/bin/getprop" directory and initialize the String which we want to get (ro.board.platform in example).
2. Make a BufferedReader which gets the value (String) by retrieving the data from a inputStreamReader().
3.Convert the BufferedReader to String.
Help your selves.
Code:
Process p = null;
String board_platform = "";
try {
p = new ProcessBuilder("/system/bin/getprop", "ro.board.platform").redirectErrorStream(true).start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line=br.readLine()) != null){
board_platform = line;
}
p.destroy();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Click to expand...
Click to collapse
Hi, Is anyone nood friendly to explain me or some tutorial where and how to put this comand, to change my build.prop without unlocking bootloader on my HOX tegra 3..grateful for any response
Hey,
Sorry for bumping this old thread.
How a non-developer user could use this to change/add build.prop lines?
I got a complete stock Nexus 5X that I'd like to add some new lines into build.prop without root.
Is it possible?
Thanks in advance!
How to integrate that to show in textView?
I am trying to check whether LG are still publicly hosting G6 bootloader unlock files online. I know you probably think but wait, we know they don't. That may not be the case.
The server may still be publicly hosting the files which device owners need to unlock their bootloaders, by reverse engineering the cached page data from the internet archives I have extracted a download link from the page.
Code:
"https://developer.lge.com/resource/mobile/common/file/DownloadFile.dev" + "?fileId=" + encodeURIComponent( json.fileId ) ;
Which appears to be missing the encoded file name. If we could get enough file names and they are indeed still publicly hosted online, we could possibly download our bootloader unlock files directly from source if we can establish a pattern in the data.
I am guessing that these file names will be in someway related to the device identifier. It's a long shot but I am willing to check it out, please help by posting the file name of the archive you extracted your unlock.bin file from this is possibly a ZIP archive you downloaded from LG website to unlock your bootloader and the file name of unlock.bin if different from unlock.bin.
Hi,
Here are the informations of an old device I owned but dead today. So it's OK to use them.
- IMEI or MEID: 356144087429995- Device ID: 662CDCF3D09A5AED38E08DB652EC4CC6F63B24DADB2332BC0C7CD30A9924D731
Jeff_i said:
Hi,
Here are the informations of an old device I owned but dead today. So it's OK to use them.
- IMEI or MEID:356144087429995- Device ID:662CDCF3D09A5AED38E08DB652EC4CC6F63B24DADB2332BC0C7CD30A9924D731
Click to expand...
Click to collapse
So it looks like the file indeed is named unlock.bin, i dont think anybody is renaming it from original name to unlock.bin
Was the file downloaded from LG in zipped format and you had unzipped it? OP would like to know the name of the original file received directly from LG if it was zipped and not as you have uploaded it here on the forum.
Right !
The attached file from lg was directly the unlock.bin file and I used it as is.
Any news?
Would there be any way to decode and re encode the unlock.bin file to use the IMEI and Device ID of your own phone?
Here are a few unlock files (from old G6 (and a G5)
Any updates ?
Please update on new ways to generate the unlock.bin. I've got an LG Stylus 2 Plus K530F and it's crazy impossible now that LG took down the site.
"Wrong Bootloader Unlock key" is what I get unfortunately
Hello,
I've take a look at the unlock.bin files shared here and this is what I've discovered:
1. when you upload the unlock.bin file, it must exactly be 1024 bytes, any other file size will give you back an error.
2. it's a null (00) padded file
3. the unlock file seems to always begin with this sequence of 20 bytes: 159e 8db7 d36b 2d7e 0001 0000 0002 0000 0100 0000
4. LG G6) contains 2 blocks of 256 bytes separated by 12 null bytes: 0000 0000 0000 0000 0000 0000
So the G6 structure seems to always be (in bytes):
20 (initial sequence) + 256 (first part) + 12 (null bytes) + 256 (second part) + 480 (padding)
4b. LG G5) after the same initial sequence (159e 8db7 d36b 2d7e 0001 0000 0002 0000 0100 0000) there is just one "block" of 256 bytes before the null padding.
Final thoughts:
I may guess that decrypting the file itself is impossible and probably the unlock keys must be extracted separately (could be as simple as):
$ head -c 276 unlock.bin | tail -c 256 > key1.bin
and (only on G6):
$ tail -c 736 unlock.bin | head -c 256 > key2.bin
If someone could share more binary files downloaded from the LG website (also for other devices) it may be useful to do more guessing about the way this files was built.
--EDIT 1
I found a post with a link to this repository:
lk/platform/lge_shared at master · jaehyek/lk
Contribute to jaehyek/lk development by creating an account on GitHub.
github.com
This made me figure how the previous models (including G5?) unlock.bin file was generated and read.
According to lge_verified_boot.c, the input structure (unlock_input_data_type) is obtained by concatenating device_id and imei taken from the phone.
All what validation (verify_image) does is comparing sha256 of it with the decoded part of unlock.bin content.
So, unlock.bin's "key1" should be obtained with: encrypt( sha256( concat( device_id, imei ) ) )
The good news is that the repository includes a "keys" folder with all the keystores used... The bad one is that I haven't found the "d2i_LGE_KEYSTORE" function that knows how to read them.
I tried again with the strategy of comparing files and discovered that there are some recurring patterns in keystores:
they seems to start with: 0x30, 0x82, 0x01
then contains some bits that identify the keystore, then:
0x30, 0x82, 0x01, 0x1f, 0x30, 0x82, 0x01, 0x1b, 0x30, 0x0b, 0x06, 0x09,
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x30, 0x82, 0x01,
0x0a, 0x02, 0x82, 0x01, 0x01, 0x00
finally, sequence ends with: 0x02, 0x03, 0x01, 0x00, 0x01.
I will write here again if I can find the public key, in order to decode the posted unlock.bin files and to collect feedback of whom posted them without imeis and device ids.
I just may need the sha256 sums of the 2 concatenated strings.
--EDIT 2
After writing a simple C program to print the Keystore inside bl_unlock.c (BLUNLOCK_KEYSTORE variable), I obtained a binary file that can be read using:
$ openssl asn1parse -in keystore -inform DER -i
0:d=0 hl=4 l= 309 cons: SEQUENCE
4:d=1 hl=2 l= 1 prim: INTEGER :00
7:d=1 hl=2 l= 13 prim: PRINTABLESTRING :UNLOCK_RSA_02
22:d=1 hl=4 l= 287 cons: SEQUENCE
26:d=2 hl=4 l= 283 cons: SEQUENCE
30:d=3 hl=2 l= 11 cons: SEQUENCE
32:d=4 hl=2 l= 9 prim: OBJECT :sha256WithRSAEncryption
43:d=3 hl=4 l= 266 cons: SEQUENCE
47:d=4 hl=4 l= 257 prim: INTEGER :92D5E3A2C6F311A1FD325C94415DF197BA1C2B307C1EDBB5D9ED109AB8A639F10D61F6582B367AAECBBF95A130E54754667565AA6A60AFA6ADD6F246048C839D017D21849F5AA2A08FA5DBDE0712694E7E80FC42A709CEE3A91A5B11873A079E0FB04E14001C6B5BB4A5DDF52E793A8D5DD4E177C560C7CEDFB8FCC844B6640B4813D629AB9B34CFD5081C5A5384225049FE0B62EFBF79728421360D3C874B387CE5B67891F8942DB431BEAAC7414ED52AFA283EA39EAD160DA51FD7F8393BAF6BBCA780DFAC477BFEF43C61E9431B85F70E4DB2CF7B0F7A410DB24D6F806C91A2C650897E9B90668D25B0A9174054E133B4382ADA5AEC3527D2F4CABE263917
308:d=4 hl=2 l= 3 prim: INTEGER :010001
--EDIT 3
First of all, I want to say that I've downloaded an OTA update of LG G6 and this can probably confirm that this keystore is still there:
LG-H87010f-Flashable.Bootloader.zip
extract and:
$ grep "UNLOCK_RSA_02" -R
grep: bootloader/aboot.img: Binary file matches
so I invested more time on it figuring how the keystore originated and found this source code of KeystoreSigner that produce the same DER sequence:
verity/KeystoreSigner.java - platform/system/extras - Git at Google
so I wrote a small Java program to print the public key in PEM format:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAktXjosbzEaH9MlyUQV3xl7ocKzB8Htu
12e0QmrimOfENYfZYKzZ6rsu/laEw5UdUZnVlqmpgr6at1vJGBIyDnQF9IYSfWqKgj6Xb3gcSaU
5+gPxCpwnO46kaWxGHOgeeD7BOFAAca1u0pd31Lnk6jV3U4XfFYMfO37j8yES2ZAtIE9Ypq5s0z
9UIHFpThCJQSf4LYu+/eXKEITYNPIdLOHzltniR+JQttDG+qsdBTtUq+ig+o56tFg2lH9f4OTuv
a7yngN+sR3v+9Dxh6UMbhfcOTbLPew96QQ2yTW+AbJGixlCJfpuQZo0lsKkXQFThM7Q4Ktpa7DU
n0vTKviY5FwIDAQAB
-----END PUBLIC KEY-----
It is a 2048-bit RSA public key, that I'm still not able to use to read the unlock files posted yet, but I share all my work just in case anybody wants to help.
-- EDIT 4
This is how I'm trying to use all the pieces I've put together. It's working now!!!
Now we have a working method to validate unlock.bin files for older phones!!!
--EDIT 5
Updated code with the working version.
-- EDIT 6
With a big thank to @ncrt that figured how the second signature is generated we now know how to completely validate the unlock.bin of G6.
This is the final version of the Java validator:
Java:
import java.io.File;
import java.math.BigInteger;
import java.nio.file.Files;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.RSAPublicKeySpec;
class Main {
private static final int UNLOCK_BIN_SIZE = 1024;
private static final int UINT32_T_SIZE = 4;
private static final int SIGNATURE_SIZE = 512;
private static final int KEY_SIZE = 256;
private static final int EXTRA_SIZE = 492;
private static final long SECURITY_UNLOCK_MAGIC1 = 2377586078L; // 0x8DB7159E
private static final long SECURITY_UNLOCK_MAGIC2 = 763286379L; // 0x2D7ED36B
private static final long SECURITY_UNLOCK_VERSION = 1L;
private static final int IMEI_SIZE = 32;
private static final int DEVICE_ID_SIZE = 96;
// RSA_UNLOCK_02
private static final RSAPublicKeySpec spec = new RSAPublicKeySpec(new BigInteger(
"18536265221834400955526124823946945144241534366405270883862606828214326557303158761374427696439760867810300046710668389940627901357786930619155280232713255180467267693281615312585736047834931276426122242381388755141769507773314618374615964530031495500324126445550145922318729183762394336526893965841523887301431217744349619177044755418369600023019646764547203434859153096499560007159303235140562773302106895748271986503337696246115511449909141742149128001718847058167094531480513164043443149146227140700654562659385941009377485565173992175722386093166833729231966326215327030617445434971297334403421561820089441204503"),
new BigInteger("65537"));
public static void main(String[] args) throws Exception {
String imei = "356144087429995";
String deviceId = "662CDCF3D09A5AED38E08DB652EC4CC6F63B24DADB2332BC0C7CD30A9924D731";
byte[] fileContent = Files.readAllBytes(new File("unlock.bin").toPath());
if (fileContent.length != UNLOCK_BIN_SIZE) {
System.err.println("Filecontent: " + fileContent.length + " expected: " + UNLOCK_BIN_SIZE);
return;
}
int offset = 0;
byte[] magic1 = new byte[UINT32_T_SIZE];
System.arraycopy(fileContent, offset, magic1, 0, UINT32_T_SIZE);
offset += UINT32_T_SIZE;
byte[] magic2 = new byte[UINT32_T_SIZE];
System.arraycopy(fileContent, offset, magic2, 0, UINT32_T_SIZE);
offset += UINT32_T_SIZE;
byte[] version = new byte[UINT32_T_SIZE];
System.arraycopy(fileContent, offset, version, 0, UINT32_T_SIZE);
offset += UINT32_T_SIZE;
byte[] hash_type = new byte[UINT32_T_SIZE];
System.arraycopy(fileContent, offset, hash_type, 0, UINT32_T_SIZE);
offset += UINT32_T_SIZE;
byte[] key_size = new byte[UINT32_T_SIZE];
System.arraycopy(fileContent, offset, key_size, 0, UINT32_T_SIZE);
offset += UINT32_T_SIZE;
if (deserialize_uint32(magic1) != SECURITY_UNLOCK_MAGIC1 || deserialize_uint32(magic2) != SECURITY_UNLOCK_MAGIC2
|| deserialize_uint32(version) != SECURITY_UNLOCK_VERSION) {
System.err.println("Magic numbers not found");
return;
}
byte[] signature = new byte[SIGNATURE_SIZE];
System.arraycopy(fileContent, offset, signature, 0, SIGNATURE_SIZE);
offset += SIGNATURE_SIZE;
byte[] extra = new byte[EXTRA_SIZE];
System.arraycopy(fileContent, offset, extra, 0, EXTRA_SIZE);
offset += EXTRA_SIZE;
byte[] input = new byte[DEVICE_ID_SIZE + IMEI_SIZE];
System.arraycopy(deviceId.getBytes(), 0, input, 0, deviceId.length());
System.arraycopy(imei.getBytes(), 0, input, DEVICE_ID_SIZE, imei.length());
final KeyFactory f = KeyFactory.getInstance("RSA");
final PublicKey publicKey = f.generatePublic(spec);
byte[] firstSignature = new byte[KEY_SIZE];
System.arraycopy(signature, 0, firstSignature, 0, KEY_SIZE);
Signature firstSignatureVerify = Signature.getInstance("NonewithRSA");
firstSignatureVerify.initVerify(publicKey);
firstSignatureVerify.update(MessageDigest.getInstance("SHA-256").digest(input));
boolean sigVerified = firstSignatureVerify.verify(firstSignature);
System.out.println("First signature verified: " + sigVerified);
byte[] secondSignature = new byte[KEY_SIZE];
System.arraycopy(signature, KEY_SIZE + 12, secondSignature, 0, KEY_SIZE - 12);
System.arraycopy(extra, 0, secondSignature, KEY_SIZE - 12, 12);
Signature secondSignatureVerify = Signature.getInstance("SHA256withRSA");
secondSignatureVerify.initVerify(publicKey);
secondSignatureVerify.update(input);
boolean sig2Verified = secondSignatureVerify.verify(secondSignature);
System.out.println("Second signature verified: " + sig2Verified);
}
private static long deserialize_uint32(byte[] b) {
long l = (long) b[0] & 0xFF;
l += ((long) b[1] & 0xFF) << 8;
l += ((long) b[2] & 0xFF) << 16;
l += ((long) b[3] & 0xFF) << 24;
return l;
}
}
Cheers
Francians
hope is fine to reserve more room....
RESERVED
francians said:
First of all, I want to say that I've downloaded an OTA update of LG G6 and this can probably confirm that this keystore is still there
Click to expand...
Click to collapse
is this at all helpful to you, or no?
LG Open Source
opensource.lge.com
francians said:
hope is fine to reserve more room....
RESERVED
Click to expand...
Click to collapse
How can I unlock my phone whit this little program?
francians said:
--EDIT 5
Updated code with the working version.
Cheers
How can I unlock my phone whit this little program?
Click to expand...
Click to collapse
That code demonstrates how the unlock works and cannot generate a file to unlock your phone. For G6 the puzzle is still uncompleted, but I am working on it. If there will be a method to unlock I'll write a dedicated post and give you a compiled software
Honkette1738 said:
is this at all helpful to you, or no?
LG Open Source
opensource.lge.com
Click to expand...
Click to collapse
The OTA will be helpful to reverse engineering it, since the source I've found is older
I was writing to the german CEO a while ago , he said no.
But maybe if we are more and write to Korea , we may have succses ?
Thats what he said :
Dear Mr W,
I have to pass. LG has not been selling cell phones for some time now and the developer services were discontinued at the end of 2021. Unfortunately, it is no longer possible to comply with your request.
For any inquiries, I'm willing to help.
.....
Definitely could be a good idea to ask them to share the private keys since without them it's currently impossible to write an unlock files generator. They may rise security concerns if such keys have been used for something else too.
marcus67 said:
I was writing to the german CEO a while ago , he said no.
But maybe if we are more and write to Korea , we may have succses ?
Thats what he said :
Dear Mr W,
I have to pass. LG has not been selling cell phones for some time now and the developer services were discontinued at the end of 2021. Unfortunately, it is no longer possible to comply with your request.
For any inquiries, I'm willing to help.
.....
Click to expand...
Click to collapse
francians said:
Definitely could be a good idea to ask them to share the private keys since without them it's currently impossible to write an unlock files generator.
Click to expand...
Click to collapse
could that be in engineering bootloaders, or likely not?