Hi Mark,
> >
> > On Thursday 06 December 2007 23:37:19 Mark Ellis wrote:
> > > Committed your patch with regards to the library functions, I'm sure
> > > what I'm seeing is nothing to do with them.
> >
> > Last night I was just thinking over what would need to be sent over the
> > line from the computer to the device and back. Unfortunately I don't have
> > a Windows machine and I don't have the WM2003 machine, but probably I
> > have some time today in the afternoon. I might test the ideas. If they
> > work out for the rapi2 calls (and would make them simpler) you could try
> > the same idea for the rapi 1 calls and see if they work out on your
> > device also. I'll keep you posted on that.
> >
> > Furthermore, did you already try to just copy the new rapi2 code to the
> > rapi1 for both the QueryInfo and the EnumValue (keep in mind that you
> > need the context_begin_command code to be the rapi1 style though!)?
>
> I had a quick go doing that, but I think in my lack of time I got it
> wrong, I'll definitely try it again.
>
> Mark
Attached you will find a new small patch against the current SVN tree. It
contains the small fix for the _debug_ routines in rapi_buffer.h.
Furthermore, still the patches for synce-registry, it is just present when I
run svn diff :)
Also there is a small update to the code of EnumValue2. I decided to look a
bit more at the actual stuff that is sent over the line and could determine
some patterns :) Within the registry2.c file I added some much needed
comments, which describe the process is far as I understand it. I did quite
some testing with sending different parameters etc and so far all testing
confirms the ideas described in the comments with EnumValue2.
Please try to copy the complete contents of enumvalue2 once to enumvalue and
only update the
rapi_context_begin_command(context, 0x34);
to
rapi_context_begin_command(context, 0x23);
due to the different code number within rapi and rapi2. It would be really
weird to me if Microsoft changed the complete protocol while going from rapi
to rapi2.
Hope the attached file provides some help with finding out why rapi1 does not
handle the EnumValue well.
Regards,
Guido Diepen
--
Aviation is proof that given the will, we have the
capacity to achieve the impossible.
--Eddie Rickenbacker
Index: src/support/rapi_buffer.h
===================================================================
--- src/support/rapi_buffer.h (revision 3077)
+++ src/support/rapi_buffer.h (working copy)
@@ -162,7 +162,7 @@
/**
* Dump the complete buffer that is supplied as parameter
*/
-void rapi_buffer_dump_buffer(
+void rapi_buffer_debug_dump_buffer(
char* desc,
RapiBuffer* buffer) ;
@@ -170,7 +170,7 @@
* Dump the remainder of the buffer that is supplied as
* a parameter. Mostly of use when dumping the recv buffer
*/
-void rapi_buffer_dump_buffer_from_current_point(
+void rapi_buffer_debug_dump_buffer_from_current_point(
char* desc,
RapiBuffer* buffer) ;
Index: src/rapi2/registry2.c
===================================================================
--- src/rapi2/registry2.c (revision 3077)
+++ src/rapi2/registry2.c (working copy)
@@ -228,11 +228,10 @@
rapi_buffer_read_int32(context->recv_buffer, &return_value);
-
+
if (ERROR_SUCCESS == return_value)
{
DWORD foo = 0 ;
-
rapi_buffer_read_uint32 (context->recv_buffer, &foo ) ;
if (lpClass)
{
@@ -280,20 +279,37 @@
LONG return_value = ERROR_GEN_FAILURE;
rapi_context_begin_command(context, 0x34);
+ //These two values are NOT allowed to be NULL, therefore, just send them
+ //right away
rapi_buffer_write_uint32 (context->send_buffer, hKey);
rapi_buffer_write_uint32 (context->send_buffer, dwIndex);
- //What is the size of the buffer we have for ValueName
- rapi_buffer_write_uint32(context->send_buffer, *lpcbValueName);
- //What is the size of the buffer we have for the data
- rapi_buffer_write_uint32(context->send_buffer, *lpcbData );
+
+
+ //After some testing, turned out that we need to tell the device the
+ //size of the buffer we have on our side. BUT, you are not allowed to
+ //send 0, probably you tell the device how much total you expect for the
+ //string to be in the reply of the device, which includes the actual
+ //length of the string
+ //
+ //The device reports |lenght|string
+ //
+ //If we send the value 00, this results in a problem, since the device
+ //can't even send the legth of the string.
+ //The length reported by the device should be 1 less then the value
+
+ //So if the user is not interested in the value
+ //(i.e. pcbData, or lpcbValueName is null) then send value 1
+
+ //Furthermore, DON'T use the write_optional, for some reason
+ //that does not work, at writes too many things to the send buffer
+ rapi_buffer_write_uint32(context->send_buffer, lpcbValueName ? *lpcbValueName : 1 );
+ rapi_buffer_write_uint32(context->send_buffer, lpcbData ? *lpcbData : 1 );
-
if ( !rapi2_context_call(context) )
return false;
-
-
+
rapi_buffer_read_uint32(context->recv_buffer, &context->last_error);
rapi_buffer_read_int32(context->recv_buffer, &return_value);
@@ -303,10 +319,22 @@
{
DWORD foo ;
- //First read the valuename
- rapi_buffer_read_string(context->recv_buffer, lpszValueName, lpcbValueName ) ;
+ //If the user wants to know the valuename
+ if (lpszValueName){
+ //First read the valuename
+ rapi_buffer_read_string(context->recv_buffer, lpszValueName, lpcbValueName ) ;
+ //Just to be sure for the moment:
+ lpszValueName[*lpcbValueName] = 0 ;
+ }
+ else{
+ //Other the value 0 will be printed to the buffer by the device, indicating
+ //the length of the string sent
+ rapi_buffer_read_uint32(context->recv_buffer, &foo) ;
+ }
+
- //Then read the type
+ //Then read the type, this is always returned by the device
+ //Just skip the value if it is not needed.
foo = 0 ;
rapi_buffer_read_uint32(context->recv_buffer, &foo );
if (lpType)
Index: tools/synce-registry.c
===================================================================
--- tools/synce-registry.c (revision 3074)
+++ tools/synce-registry.c (working copy)
@@ -13,14 +13,20 @@
#define ACTION_LISTKEY 3
#define ACTION_NEWKEY 4
#define ACTION_DELETEKEY 5
+#define ACTION_DUMP_REGISTRY 6
+
char* devname = NULL;
int action = ACTION_READVAL;
+bool list_recurse = false ;
DWORD valType = REG_SZ;
const char *prog_name;
#define STR_EQUAL(a,b) (0 == strcasecmp(a,b))
+int read_val(char *parent_str, char *key_str, HKEY key, LPCWSTR value_name_wide) ;
+
+
static void show_usage(const char* name)
{
fprintf(stderr,
@@ -39,6 +45,8 @@
"\t 1 - Errors only\n"
"\t 2 - Errors and warnings\n"
"\t 3 - Everything\n"
+ "\t-D Dump complete registry to screen\n"
+ "\t-L Enable list recursion\n"
"\t-h Show this help message\n"
"\t-p DEVNAME Mobile device name\n"
"\t-t TYPE New type for writes:\n"
@@ -94,7 +102,7 @@
{
int c;
int log_level = SYNCE_LOG_LEVEL_LOWEST;
- while ((c = getopt(argc, argv, "d:hp:t:rwxlnX")) != -1)
+ while ((c = getopt(argc, argv, "d:hp:t:rwxlnXDL")) != -1)
{
switch (c)
{
@@ -102,6 +110,9 @@
log_level = atoi(optarg);
break;
+ case 'L':
+ list_recurse = true ;
+ break ;
case 'p':
devname = optarg;
break;
@@ -130,7 +141,11 @@
action = ACTION_DELETEKEY;
break;
- case 't':
+ case 'D':
+ action = ACTION_DUMP_REGISTRY;
+ break;
+
+ case 't':
if (strcasecmp(optarg,"binary") == 0)
{
valType = REG_BINARY;
@@ -275,18 +290,58 @@
return 0;
}
-int list_key(HKEY key)
-{
+
+int list_key(HKEY key, char* key_path, bool do_recurse)
+{
+ //First print the path till now:
+ printf("\n[%s]\n", key_path );
+
+
int result;
int i;
+
+ //First determine the size of the holding arrays for all
+ //subvalues/keys
+ DWORD lpcSubKeys ;
+ DWORD lpcbMaxSubKeyLen ;
+ DWORD lpcbMaxClassLen ;
+ DWORD lpcValues ;
+ DWORD lpcbMaxValueNameLen ;
+ DWORD lpcbMaxValueLen ;
+
+ result = CeRegQueryInfoKey(key, NULL, NULL, NULL,
+ &lpcSubKeys, &lpcbMaxSubKeyLen, &lpcbMaxClassLen,
+ &lpcValues, &lpcbMaxValueNameLen, &lpcbMaxValueLen,
+ NULL, NULL) ;
+
+ //One important thing is to add +1 to all string lengths, since we need to
+ //add the zero-terminator also, which is not present in the device.
+
+ lpcbMaxClassLen++ ;
+ lpcbMaxValueNameLen++ ;
+ lpcbMaxValueLen++ ;
+ lpcbMaxSubKeyLen++ ;
+
+
+
+ //First print all of the values
for(i = 0; ; i++)
{
- WCHAR wide_name[MAX_PATH];
- DWORD name_size = sizeof(wide_name);
-
- result = CeRegEnumKeyEx(key, i, wide_name, &name_size, NULL, NULL,
- NULL, NULL);
+ DWORD value_name_wide_size = lpcbMaxValueNameLen ;
+ WCHAR value_name_wide[value_name_wide_size];
+
+ DWORD value_size = lpcbMaxValueLen ;
+ uint8_t value[value_size];
+
+ DWORD value_type;
+
+
+
+ result = CeRegEnumValue(key, i, value_name_wide ,
+ &value_name_wide_size, NULL, &value_type,
+ value , &value_size );
+
if (ERROR_NO_MORE_ITEMS == result)
break;
else if (ERROR_SUCCESS != result)
@@ -296,16 +351,33 @@
synce_strerror(result));
return 1;
}
- printf("K %s\n",wstr_to_ascii(wide_name));
+
+ printf("\"%s\"=", wstr_to_ascii(value_name_wide));
+
+ switch (value_type)
+ {
+ case REG_SZ:
+ printf("\"%s\"\n", wstr_to_ascii((LPCWSTR)value));
+ break;
+
+ case REG_DWORD:
+ printf("dword=%08x\n", *(DWORD*)value);
+ break;
+
+ default:
+ dump("Value", value, value_size);
+ break;
+ }
}
+
for(i = 0; ; i++)
{
+
WCHAR wide_name[MAX_PATH];
DWORD name_size = sizeof(wide_name);
- DWORD type;
- result = CeRegEnumValue(key, i, wide_name, &name_size, NULL, &type,
+ result = CeRegEnumKeyEx(key, i, wide_name, &name_size, NULL, NULL,
NULL, NULL);
if (ERROR_NO_MORE_ITEMS == result)
break;
@@ -316,15 +388,81 @@
synce_strerror(result));
return 1;
}
- /* TODO: We already have the value type, might as well display it. */
- /* TODO: We have the value itself, too, so maybe just display that. */
- /* TODO: It's probably pretty easy to make this work recursively, while we're at it */
- /* TODO: Which would be a pretty good registry dump tool. */
- printf("V %s\n",wstr_to_ascii(wide_name));
+
+
+ if (!do_recurse){
+ //Then just print all the subkeys
+ printf("\n") ;
+ fprintf(stdout, "[%s\\%s]\n", key_path, wstr_to_ascii(wide_name)) ;
+ }
+ else{
+ HKEY childKey = 0 ;
+ char* child_key_name = wstr_to_ascii( wide_name ) ;
+ char child_key_path[MAX_PATH] ;
+ sprintf(child_key_path,"%s\\%s", key_path, child_key_name) ;
+
+ if (!rapi_reg_open_key( key, child_key_name, &childKey ))
+ {
+ return 1 ;
+ }
+
+ //We have childkey now
+ //Do list_key on this
+ list_key( childKey , child_key_path, do_recurse) ;
+ }
}
- return 0;
+
+
+ return 0 ;
}
+
+
+
+int dump_registry()
+{
+ //First the HKLM
+ HKEY rootKey = HKEY_LOCAL_MACHINE ;
+
+ int result = 0 ;
+
+ result = list_key( rootKey, "HKEY_LOCAL_MACHINE", true) ;
+
+ if (result != 0){
+ return result ;
+ }
+
+ //Then the HKCU
+ rootKey = HKEY_CURRENT_USER ;
+
+ result = 0 ;
+
+ result = list_key( rootKey, "HKEY_CURRENT_USER", true ) ;
+
+ if (result != 0){
+ return result ;
+ }
+
+
+
+ //And finally the HKCR
+ rootKey = HKEY_CLASSES_ROOT ;
+
+ result = 0 ;
+
+ result = list_key( rootKey, "HKEY_CLASSES_ROOT", true ) ;
+
+ if (result != 0){
+ return result ;
+ }
+
+ return 0 ;
+}
+
+
+
+
+
int delete_val(HKEY key, LPCWSTR value_name)
{
#if 0
@@ -345,6 +483,7 @@
}
+
int read_val(char *parent_str, char *key_str, HKEY key, LPCWSTR value_name_wide)
{
int error;
@@ -453,7 +592,36 @@
if (!handle_parameters(argc,argv,&parent_str,&key_name,&value_name,&new_value))
goto exit;
-
+
+
+ //Add this before anything, since we don't need the
+ //parent_str etc..
+ if (action==ACTION_DUMP_REGISTRY){
+ if ((connection = rapi_connection_from_name(devname)) == NULL)
+ {
+ fprintf(stderr, "%s: Could not find configuration at path '%s'\n",
+ argv[0],
+ devname?devname:"(Default)");
+ goto exit;
+ }
+ rapi_connection_select(connection);
+ if (S_OK != (hr = CeRapiInit()))
+ {
+ fprintf(stderr, "%s: Unable to initialize RAPI: %s\n",
+ argv[0],
+ synce_strerror(hr));
+ goto exit;
+ }
+
+ result = dump_registry() ;
+ if (result != 0){
+ fprintf(stdout, "SOMETHING WENT WRONG!!!!\n" ) ;
+ }
+ goto exit;
+ }
+
+
+
/* handle abbreviations */
if (STR_EQUAL(parent_str, "HKCR"))
parent_str = "HKEY_CLASSES_ROOT";
@@ -516,7 +684,9 @@
if (action == ACTION_LISTKEY)
{
- result = list_key(key);
+ char path[255] ;
+ sprintf(path,"%s\\%s", parent_str, key_name ) ;
+ result = list_key(key, path, list_recurse);
goto exit;
}
-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
SynCE-Devel mailing list
SynCE-Devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/synce-devel