This project is read-only.

Problem saving entry with alternatePhoneNumbers set

Mar 3, 2010 at 10:45 AM

Hi, I have a problem setting alternatePhoneNumbers in an existing entry and then trying to update it.

I always get the error: 'length' specified is longer than the string.

Checking the source code I can see that when the entry is saved this method is called:

Utilities.CopyString(lpRasEntry, size, alternatesList, alternatesLength);

where alternatsList and alternatesLength where obtained this way:

alternatesList = Utilities.BuildStringList(value.AlternatePhoneNumbers, '\x00', out alternatesLength);

BuildStringList after concatenate all its values with the separator char in a string builder, returns alternatesLength as the double of the size of the stringBuilder:

length = sb.Length * 2;
Going to the CopyString implementation the following appears:

static void CopyString(IntPtr ptr, int offset, string value, int length)
if (value == null)

if (length > value.Length)
ThrowHelper.ThrowArgumentException("length", Resources.Argument_ValueLongerThanString);

As can you see, in the second if, 'length' always double 'value.length', throwing the argument exception everytime.

Am I missing something?

If you confirm that this is ok, what must I do to save the alternatePhoneNumbers in an entry?

Mar 3, 2010 at 2:25 PM

The length is doubled due to the assembly using the RasSetEntryPropertiesW (unicode) call. Modifying them should be as simple as entry.AlternatePhoneNumbers.Add("1234567890"); and then calling entry.Update();. That method must check if the length of the string you're trying to copy is longer than the length of the string you're actually passing into it, so that isn't the issue.

What operating system are you using, and how are you modifying the alternate numbers collection?

Keep in mind, there are issues with DotRas and using the alternate numbers list as indicated at the top of the discussions list. This problem doesn't seem to be related to that, but it may be.

Mar 3, 2010 at 7:36 PM

Thanks Jeff for your response.

I'm trying in Windows 7 (I know that is unsupported) and Vista 64.

I'm using just as you said:


And always get the exception.

What I can't get, it is that you said that the lengt is doubled because the use of unicode but if I don't bad understand , in

if (length > value.Length)
it is comparing the length calculated from the stringBuilder (wich was doubled) with the length of the same string (not doubled) in pure .net strings, then when debugging
I can see what for me is ok, that length is the double of value.length.

I don't know if I'm clear (I'm not an english speaking person), if you have some doubt ask me that I'll try to explain the best that I can.

I appreciate your help. Thanks
Mar 3, 2010 at 9:54 PM

You should be using two versions of the DLL to manage both operating systems.

You are using the WIN7 and WIN2K8 compiled versions for Windows 7 and Windows Vista respectively aren't you?

It might be a bug in the code, I haven't touched that code in ages since I worked on it last. I'll do some testing on my Win7 box tonight and see what I come up with. Check back with me tomorrow sometime.

Mar 3, 2010 at 10:00 PM

Thank you, I'll check it tomorrow then.

I'm using WINXPSP2 that is the oldest version targeted (what I understood was that I should do that).


Mar 3, 2010 at 10:09 PM

For your information, there's a problem with the Win32 RAS API that I've reported to Microsoft (it's noted on the top of the discussions page) that you should use the version built for each OS. If you want more info on that, you can look at the link to the Microsoft Connect website where I reported the bug. I don't know when it's going to be available to the other operating systems, so doing that will be entirely use at your own risk. I won't fix that bug, since it's an issue with the OS at that point.

In short: If you need to support alternate numbers for a dial-up entry, you can have severe issues with this project overwriting random blocks of memory if you aren't using the version built for that operating system.

Until Microsoft fixes the issue in their operating system and releases a service pack containing the fix, working with alternate entries with this project can get tricky.

Mar 3, 2010 at 10:09 PM

Last comment until tomorrow, put a breakpoint in 

if (length > value.Length) in the CopyString method

after adding a number and calling update to see my point...
This is my code:

            var entry = this.AllUsersPhoneBook.Entries["AconnectionName"];

AllUsersPhonebook is a component in a form (was test it using your example)

Mar 3, 2010 at 11:31 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Mar 3, 2010 at 11:41 PM
Edited Mar 3, 2010 at 11:55 PM

You were correct about the method not working properly, that check should have never been there. If anything it should have been testing the size of the memory block allocated to make sure copystring doesn't exceed that boundary and start overwriting random bits in memory, but that isn't necessary. I also fixed another minor bug with alternate entries during the retrieval process, it wouldn't retrieve more than one at a time. Just get latest and compile the project if you want it fixed immediately. There are compilation instructions on the Documentation tab if you need help getting the project to compile.

Thanks for reporting the bug, let me know if you find any others!

- Jeff

Mar 4, 2010 at 12:45 AM

You're welcome, if I found something else, I'll let you know, but I was trying it for a couple of days and I think you did a great work, thank you very much.

I'll try to compile the last version and follow you're suggestion to use differents compilations for different versions of the OS. 

Last question, can I compile against the xpsp2 version and then change just the dll depending on the version of the operating system where the software will run?

Mar 4, 2010 at 5:50 AM

To be honest, I'm not entirely sure. You can always try it and see what happens. The file version is set for 1.1, but the assembly version is set to 1.1.* in the project. I do this so I can differentiate which compiled version of the project people are using when they come to me asking questions why it doesn't work on a specific operating system.