RegEnumKeyEx causes native exception on PPC2002

B

Benjamin Lukner

Hi!

I tried to enumerate the registry via RegOpenKeyEx / RegEnumKeyEx /
RegCloseKey ("W" versions). It works fine on PPC2003 (I tested 5
terminals from different manufacturers with CE.Net and PPC2003), but on
most PPC2002 (3 of 4 tested) I get a "native exception".

I use TRY / CATCH / END TRY, but the program crashes without handling
the error. It crashes at different keys of the registry.

On one Pocket PC 2002 it worked. Strange: on a nearly identical one it
crashed (Symbol PDT8146, one with Symbol and one with Avaya WLAN card).

Very strange: To find the location in the source code where it crashed I
inserted writing numbers into a file (wrapped WriteFile API call) before
and after the RegEnumKeyEx call. IT NEVER CRASHES WITH THAT EXTENSION!
After removing the WriteFile it crashed again.

Does anyone know a(nother) workaround for this problem?


Kind regards,

Benjamin Lukner
 
C

Chris Tacke, eMVP

Without seeing code, we're all guessing. Take a look at OpenNETCF.org's
implementation and compare it to your own.
 
B

Benjamin Lukner

Without seeing code, we're all guessing.

Yeah, you're right... ;-)
Take a look at OpenNETCF.org's
implementation and compare it to your own.

I had a look at that implementation.
But I work with VB.Net.
It's very hard to say if I should declare a parameter ByVal or ByRef.
(E.g. when using Strings or Byte Arrays, I always have to use ByVal)
Altering the Class parameters to work with "Nothing" (Null) throws an
error when accessing Classes_Root\CLSID.

So I still get the native exception :-(
(Even after spending 5 more hours on that problem)

I compacted my code as far as possible.
Perhaps someone might test it on an Pocket PC 2002:


Module Module1

Declare Function RegEnumKeyEx Lib "coredll.dll" _
Alias "RegEnumKeyExW" ( _
ByVal hKey As Int32, _
ByVal dwIndex As Int32, _
ByVal lpName As String, _
ByRef lpcbName As Int32, _
ByVal lpReserved As Int32, _
ByVal lpClass As String, _
ByRef lpcbClass As Int32, _
ByVal lpftLastWriteTime As Int32 _
) As Int32

Declare Function RegOpenKeyEx Lib "coredll.dll" _
Alias "RegOpenKeyExW" ( _
ByVal hKey As Int32, _
ByVal lpSubKey As String, _
ByVal ulOptions As Int32, _
ByVal samDesired As Int32, _
ByRef phkResult As Int32 _
) As Int32

Declare Function RegCloseKey Lib "coredll.dll" _
Alias "RegCloseKey" ( _
ByVal hKey As Int32 _
) As Int32

Const HKEY_LOCAL_MACHINE = &H80000002

Const ERROR_SUCCESS = 0
Const ERROR_INVALID_PARAMETER = 87
Const ERROR_MORE_DATA = 234
Const ERROR_NO_MORE_ITEMS = 259


Sub Main()
EnumerateSections(HKEY_LOCAL_MACHINE, "")
MsgBox("Finished.")
End Sub


Sub EnumerateSections(ByVal uHKEY As Int32, ByVal sSection As String)

Dim sSubSection As String

Try
For Each sSubSection In RegEnumerateSections(uHKEY, sSection)
'MsgBox(sSection + "\" + sSubSection)
EnumerateSections(uHKEY, sSection + "\" + sSubSection)
Next
Catch ex As Exception
MsgBox(ex.ToString + ": " + uHKEY.ToString + sSection)
End Try

End Sub


Function RegEnumerateSections(ByVal ClassKey As Int32 _
, ByVal SectionKey As String) As Collection

Dim lKeyHandle As Int32
Dim lIndex As Int32 = 0
Dim sBuffer As String
Dim lBufferLen As Int32 = 1024
Dim sClass As String
Dim lClassLen As Int32 = 1024

Dim colSections As New Collection

If RegOpenKeyEx(ClassKey, SectionKey, 0, 0, lKeyHandle) _
= ERROR_SUCCESS Then

Do
sBuffer = Space(lBufferLen)
sClass = Space(lClassLen)

Select Case RegEnumKeyEx(lKeyHandle, lIndex, sBuffer, lBufferLen _
, 0, sClass, lClassLen, 0)
Case ERROR_MORE_DATA
lBufferLen *= 2
lClassLen *= 2
Case ERROR_SUCCESS
colSections.Add(sBuffer.Substring(0, sBuffer.IndexOf(Chr(0))))
lBufferLen = 1024
lClassLen = 1024
lIndex += 1
Case ERROR_INVALID_PARAMETER
Throw New Exception("RegEnumKeyEx: Invalid parameter.")
Case Else
Exit Do
End Select
Loop

RegCloseKey(lKeyHandle)
End If

Return colSections

End Function

End Module



Kind regards,

Benjamin Lukner
 
P

Paul G. Tobey [eMVP]

The only thing wrong that I see is that, if the key you find is too large,
you *cannot* just change the length value passed to it and try again. You
have to actually resize the buffer into which the return data is to be
written. When you receive ERROR_MORE_DATA, what you are doing is wrong.
Further, you need to make sure that the string into which you are having the
data written is allocated to begin with to have the length that you are
telling the registry call it has.

Paul T.
 
B

Benjamin Lukner

Paul said:
The only thing wrong that I see is that, if the key you find is too large,
you *cannot* just change the length value passed to it and try again. You
have to actually resize the buffer into which the return data is to be
written. When you receive ERROR_MORE_DATA, what you are doing is wrong.
Further, you need to make sure that the string into which you are having the
data written is allocated to begin with to have the length that you are
telling the registry call it has.

The problem doesn't seem to be wrong code written by me BUT a "timing"
problem of Pocket PC 2002.
The same code works on ALL tested PPC 2003 from three different
manufacturers, but only on ONE PPC 2002 of six tested.
It also works on PPC 2002 if I write to a file before and after the
RegEnumKeyEx call !!!

I compacted the code as much as possible. So if you have a closer look
you'll see that the length of the value and string aren't wrong:

Dim lBufferLen As Int32 = 1024
Dim lClassLen As Int32 = 1024
Do
sBuffer = Space(lBufferLen) ' BUFFER 1 INIT HERE
sClass = Space(lClassLen) ' BUFFER 2 INIT HERE

Select Case [...] ' FUNCTION CALL HERE
Case ERROR_MORE_DATA
lBufferLen *= 2
lClassLen *= 2
Case ERROR_SUCCESS
lBufferLen = 1024
lClassLen = 1024
Loop

<Marvin>
I think you ought to know that I'm feeling very depressed.
</Marvin>


So long and kind regards

Benjamin Lukner
 
B

Benjamin Lukner

Paul said:
The only thing wrong that I see is that, if the key you find is too large,
you *cannot* just change the length value passed to it and try again. You
have to actually resize the buffer into which the return data is to be
written. When you receive ERROR_MORE_DATA, what you are doing is wrong.
Further, you need to make sure that the string into which you are having the
data written is allocated to begin with to have the length that you are
telling the registry call it has.

If I debug the program line by line no error occurs.
If I run the program in debug mode from the .Net IDE or directly on the
Pocket PC 2002 as released version the exception occurs.

It's very frustrating....


Kind regards,

Benjamin Lukner
 
P

Paul G. Tobey [eMVP]

I would start out by *fixing the known problems*. Who knows what might be
causing the 'timing' problem? Something is open, so a long binary key is
added to the registry... When you enumerate it, it happens to expose the
problem I described...

Paul T.
 
B

Benjamin Lukner

Paul said:
I would start out by *fixing the known problems*. Who knows what might be
causing the 'timing' problem? Something is open, so a long binary key is
added to the registry... When you enumerate it, it happens to expose the
problem I described...

I NEVER run into ERROR_MORE_DATA.
And the buffers aren't initialized wrong as
I posted this morning:

Dim lBufferLen As Int32 = 1024
Dim lClassLen As Int32 = 1024
Do
sBuffer = Space(lBufferLen) ' BUFFER 1 INIT HERE
sClass = Space(lClassLen) ' BUFFER 2 INIT HERE

Select Case [...] ' FUNCTION CALL HERE
Case ERROR_MORE_DATA
lBufferLen *= 2
lClassLen *= 2
Case ERROR_SUCCESS
lBufferLen = 1024
lClassLen = 1024
Loop

I checked the OpenNet implementation. There only a 256 byte buffer is
used and no handling of ERROR_MORE_DATA. It's written in C# and works.

So I'd say it's a problem between VB.Net CF and PPC 2002
OR
something else. ;-)

I haven't found a VB.Net CF implementation of that function yet.
So I don't know what to do with it next...


Kind regards,

Benjamin Lukner
 
P

Paul G. Tobey [eMVP]

Just so I understand, also, are you saying that the OpenNetCF implementation
works on the devices where your implementation in VB.NET does not work?

Maybe posting the whole thing (or the smallest program that does the same
stuff and still crashes), is the best way to proceed. If it fails and
nothing else can be figured out, at least MS will have a case to test for a
run-time bug.

Paul T.

Benjamin Lukner said:
Paul said:
I would start out by *fixing the known problems*. Who knows what might be
causing the 'timing' problem? Something is open, so a long binary key is
added to the registry... When you enumerate it, it happens to expose the
problem I described...

I NEVER run into ERROR_MORE_DATA.
And the buffers aren't initialized wrong as
I posted this morning:

Dim lBufferLen As Int32 = 1024
Dim lClassLen As Int32 = 1024
Do
sBuffer = Space(lBufferLen) ' BUFFER 1 INIT HERE
sClass = Space(lClassLen) ' BUFFER 2 INIT HERE

Select Case [...] ' FUNCTION CALL HERE
Case ERROR_MORE_DATA
lBufferLen *= 2
lClassLen *= 2
Case ERROR_SUCCESS
lBufferLen = 1024
lClassLen = 1024
Loop

I checked the OpenNet implementation. There only a 256 byte buffer is
used and no handling of ERROR_MORE_DATA. It's written in C# and works.

So I'd say it's a problem between VB.Net CF and PPC 2002
OR
something else. ;-)

I haven't found a VB.Net CF implementation of that function yet.
So I don't know what to do with it next...


Kind regards,

Benjamin Lukner
 
B

Benjamin Lukner

Paul said:
Just so I understand, also, are you saying that the OpenNetCF implementation
works on the devices where your implementation in VB.NET does not work?
Exactly.

Maybe posting the whole thing (or the smallest program that does the same
stuff and still crashes), is the best way to proceed.

In my posting from 26.02.2004 15:14 GMT+1 I already posted the source
code. It is ONE Module with a Sub Main. (I mean the posting you've
replied to first.) It IS the smallest programm possible that does the
same stuff and still crashes. The "*= 2" is no good idea, I know. But
those code lines have NEVER been reached during my tests...
If it fails and
nothing else can be figured out, at least MS will have a case to test for a
run-time bug.

I haven't found another VB.Net CF implementation of that code, as I
said. I also said that if I write dummy strings before and after the api
calls to a file to find the erroneous code my code WORKS PERFECT. It
ALSO works if I step through the code line by line in the debugger. And
I also asked if someone could run the code and check if it crashes.

I've spent 3 whole days on this single code line now (the RegEnumKeyEx
call).
It ONLY does not work on a Pocket PC 2002 with VB.Net CF.
So I don't know what more to test, try or check to get it working.
This morning I found two more grey hairs, so please help ;-)


Yours sincerely,
Benjamin Lukner
 
P

Paul G. Tobey [eMVP]

OK, I've run it on our devices and it works fine, but that's no surprise as
you're successful on PPC2003 and our devices are based on CE.NET 4.2, also.

Since no one from MS has yet joined, you should probably contact PSS and
report it as a bug.

Sorry you're having so much trouble...
Paul T.
 
B

Benjamin Lukner

Paul said:
OK, I've run it on our devices and it works fine, but that's no surprise as
you're successful on PPC2003 and our devices are based on CE.NET 4.2, also.

Since no one from MS has yet joined, you should probably contact PSS and
report it as a bug.

I just tried encapsulating (ONLY!) the both calls in a C# dll:

public static int EnumKeyEx(
uint hKey,
int iIndex,
char[] sKeyName,
ref int iKeyNameLen)
{
return RegEnumKeyEx(hKey, iIndex,
sKeyName, ref iKeyNameLen,
0, null, 0, 0);
}

public static int EnumValue(
uint hKey,
int iIndex,
char[] sValueName,
ref int iValueNameLen,
ref int iType,
byte[] byData,
ref int iDataLen)
{
return RegEnumValue (hKey, iIndex,
sValueName, ref iValueNameLen,
0, ref iType,
byData, ref iDataLen);
}

and.... TADAAAAAAA
It works fine without throwing a native exception!

So it REALLY seems to be a problem with VB.Net CF and PPC 2002.


Kind regards,

Benjamin Lukner
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top