Why does the wireless connection dialog ask for your password twice?

Martin wonders why the wireless networking dialog asks you to type your password twice when connecting to an existing network.

Yeah, that bothers me too, and I don't know why either.

But while we're on the topic of wireless networking, I thought I'd share a little program that is just as useless as my answer above. (If other people get to hijack the topic, then I want to also.)

Back in the early days of Windows XP, I found that my wireless networking adapter would constantly disconnect and reconnect. I never figured out why, but I did have a theory. (Theory: The wireless zero configuration service saw another access point and said, "Hey, that access point over there looks much nicer than then one I'm currently connected to. I'm going to drop my current connection and see if maybe that other access point will go out with me." And then it went up to that other access point and asked it out on a date. When the other access point said no, it came crawling back to the original access point. Repeat.)

Anyway, to avoid this problem (which went away after a while for reasons unclear; maybe it was fixed, maybe whatever situation triggered the problem went away, I didn't bother investigating), I wrote a program which did two very simple things:

  1. If the wireless networking adapter was connected to an access point, then turn off the wireless zero configuration service.

  2. If the wireless networking adapter was not connected to an access point, then turn on the wireless zero configuration service.

In other words, it automates the process described on this Web page. (I like how that article was copied in its entirety to another site, which replaced the author's name. Now that's chutzpah.)

Mind you, the program really is no longer interesting in and of itself any more because the underlying problem went away, but I thought it could serve as an illustration of how you can put together some simple things to make a useful tool.

First, I changed the security descriptor on the wireless zero configuration service so that my account had permission to turn it on and off.

Second, I added this code to a program that hangs out my Startup group which monitors various things I like to monitor. (I have one program that monitors several things just to cut down on the number of processes hanging around on my machine.) The code has been compressed and reformatted to get rid of the uninteresting parts.

class MonitorWireless
    : m_hWait(NULL)
      ZeroMemory(&m_o, sizeof(m_o));

    if (m_hWait) UnregisterWaitEx(m_hWait, INVALID_HANDLE_VALUE);
    if (m_o.hEvent) CloseHandle(m_o.hEvent);

  BOOL Initialize();

  static void CALLBACK s_OnChange(PVOID lpParameter, BOOLEAN)
    MonitorWireless *self =
    self->CheckIPAddress(); // something changed - check it again

  void CheckIPAddress();
  static void StartStopService(BOOL fStart);

    HANDLE m_hWait;

The class definition is all very boring. Our class has an OVERLAPPED structure which we use to register for IP address change notifications, and it has a handle to a registered wait, which takes advantage of the thread pool to reduce the number of threads used by the process.

BOOL MonitorWireless::Initialize()
  m_o.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  if (!m_o.hEvent) return FALSE;
  if (!RegisterWaitForSingleObject(&m_hWait, m_o.hEvent,
                      s_OnChange, this, INFINITE, 0)) return FALSE;
  return TRUE;

When the object is initialized, it creates the handle that we will ask to be set whenever the computer's IP address changes, and then registers a wait on that handle with a callback function. When the event is signaled, we check the IP address. And to start the ball rolling, we check the IP address at initialization.

void MonitorWireless::CheckIPAddress()
  ULONG ulSize = 0;
  if (GetIpAddrTable(NULL, &ulSize, 0) ==
                                     ERROR_INSUFFICIENT_BUFFER) {
    PMIB_IPADDRTABLE piat = reinterpret_cast<PMIB_IPADDRTABLE>
                                (LocalAlloc(LMEM_FIXED, ulSize));
    if (piat) {
      if (GetIpAddrTable(piat, &ulSize, 0) == ERROR_SUCCESS) {
        BOOL fFound = FALSE;
        for (DWORD dwIndex = 0; dwIndex < piat->dwNumEntries;
             dwIndex++) {
          PMIB_IPADDRROW prow = &piat->table[dwIndex];
          if (prow->dwAddr == 0) continue;
          if ((prow->wType & (MIB_IPADDR_DYNAMIC |
                              MIB_IPADDR_DELETED |
                              MIB_IPADDR_DISCONNECTED)) !=
                              MIB_IPADDR_DYNAMIC) continue;
          fFound = TRUE;

  NotifyAddrChange(&h, &m_o);

We start by getting the IP address table (doing the standard two-step of first asking how much memory we need to hold it, allocating the memory, and then filling the buffer) and walking through each IP address. If we find an entry with an IP address that is dynamic, not deleted, and not disconnected, then we declare ourselves happy; otherwise we are sad. If we are happy, then we stop the wireless zero configuration service; if we are sad, then we start it.

void MonitorWireless::StartStopService(BOOL fStart)
  if (sc) {
    SC_HANDLE scWzcsvc = OpenService(sc, TEXT("wzcsvc"),
                   fStart ? SERVICE_START 
                          : SERVICE_STOP | SERVICE_QUERY_STATUS);
    if (scWzcsvc) {
      if (fStart) StartService(scWzcsvc, 0, NULL);
      else        StopService(scWzcsvc);

To start or stop the service, we first connect to the service control manager, open the service we want to start/stop, and then, well, start or stop it.

There is already a Start­Service function, but no Stop­Service function, so I wrote my own:

void StopService(SC_HANDLE sc)

 if (QueryServiceStatus(sc, &ss) &&
     ss.dwCurrentState != SERVICE_STOPPED &&
     ss.dwCurrentState != SERVICE_STOP_PENDING)
   ControlService(sc, SERVICE_CONTROL_STOP, &ss);

If the service is not already stopped (or stopping), then we tell it to stop.

And there you have it, a program that you don't need any more. But the point here was more to show how you can put together some basic elements to solve a simple problem.

Techniques illustrated:

  • Registering a wait in the thread pool.
  • Registering asynchronously for IP address changes.
  • Starting and stopping a service.
Comments (33)
  1. Nerf says:

    And, of course, the proper way to allocate memory.  Failure to do so being the #1 cause of security holes (as determined by me)

  2. JJJ says:

    I’m going to guess that the person who worked on the wireless networking dialog was someone who was used to working with cryptographic modules that go up for FIPS 140-2 certification, which states that manually entered keying material needs verification.  One method of verification is requiring that the user enter the data twice.

    Maybe it’s not necessary, I don’t know.  But they probably figured that providing keying material for the underlying crypto library fell under the standard.

  3. Gabe says:

    JJJ: The reason you have to type your passphrase twice is presumably because you can’t see it. The actual problem is that this passphrase is treated as secret like a password when it usually isn’t. They should just have a checkbox that lets you hide it if necessary, and only make you enter it twice if it’s hidden.

    While we’re hijacking discussions, I have this cellular modem which requires a little app to connect to the network. At some point my cellular carrier decided that their app should also handle WiFi connections too, which I didn’t want, so I disabled it. Unfortunately in their eagerness to provide this functionality they stop the wireless zero configuration service even when you have the WiFi part of the app disabled. I’m sure the app’s authors were thinking "Why would they ever need to use Windows’ built-in WiFi applet? They have ours which is much better!" (and nobody ever got promoted for not including a feature).

    So anyway, I’ve been wanting to write an app that detected that my WiFi wasn’t connected and wzcsvc wasn’t running, but I didn’t know how. Thank you for one of the most useful code samples you’ve posted.

  4. Malcolm says:

    I hope praise like the article above has made your day, Raymond :)

  5. Alexandre Grigoriev says:


    "They should just have a checkbox that lets you hide it if necessary, and only make you enter it twice if it’s hidden."

    I see that you’ve never set up wireless in Vista+7?


    GetIpAddrTable doesn’t require LocalAlloc. In fact, the msdn example for it uses plain HeapAlloc.


    Using reinterpret_cast for PVOID casts is not required. static_cast works. Generally, you should be using least forceful cast when possible, to let the compiler warn you of possible errors. reinterpret_cast is a hammer too big for that purpose.

  6. Alexandre Grigoriev says:

    Me: "reinterpret_cast is a hammer too big for that purpose."

    I’d add that it’s a kind of hammer for beating a square peg into a round hole.

  7. Chris Lineker says:

    This would be a great app for netbooks if it also detected when the wifi card was disabled and stopped the service then too. But I suspect that detecting the power state of the card would be 1) hard 2) different from model to model

    [It was just a demonstration of how you can combine little things to make something interesting. Simply repeat the process for any new features you like. -Raymond]
  8. Alexandre Grigoriev says:

    @Chris Lineker,

    Register for GUID_DEVINTERFACE_NET notifications and find out if any of enabled NICs is wireles and powered up.

  9. Marquess says:

    Best. Introduction. Ever.

  10. Miral says:

    Recently I was forced to fall back on a wireless connection (via USB dongle) and was plagued by it dropping the connection (and refusing to reconnect due to an unspecified error) every once in a while.

    I’m not sure which component was at fault (though I suspect the drivers), but disabling and then re-enabling the connection from Network Connections invariably fixed it.  (Nothing else seemed to.)

    If I were forced to use wireless more often then I’d probably be tempted to write a similar app to this myself.  (Or to find an alternate wireless adaptor.)

  11. Mike Dunn says:

    The answer to the original question is: Someone copied someone else’s bad design without thinking it through. It’s like when a web signup form asks you to enter your email address twice. The email edit boxes don’t have the password style set, so copy & paste works, thus defeating the supposed error-checking of making you type it twice. But enough people have seen it designed that way that they think it’s the right thing to do.

  12. anon says:

    A similar problem exists in Windows Vista 32 bit. I had to download WLAN Optimizer, and that reduced the problem, but it didnt go away completely. Will give your code a try and how that works out! Thanks!

  13. Anonymuos says:

    Why was the wireless provisioning services feature dropped in Vista/Server 2008? It was very useful for clients to auto configure wireless settings using XML files.

  14. Neil says:

    So, why does StopService care about whether the service was already started?

    @Gabe: There are, or at least were, several wireless drivers which thought that stopping the wireless zero configuration service was the right thing to do when they wanted to use their own UI. (Yes I have multiple wireless NICs.)

  15. Random832 says:

    "JJJ: The reason you have to type your passphrase twice is presumably because you can’t see it."

    I can’t see my login password, but I only have to type it twice when I change it, not when I use it.

  16. Grumpy says:

    (If other people get to hijack the topic, then I want to also.)

    Give yourself a star. That was pure gold. Thank you for saving my day.

  17. !share says:

    When editing a docx document in sharepoint you have to enter your credentials three times! I love the seamless integration between ms products.

  18. Joe says:

    I had a look at the documentation for GetIpAddrTable and it doesn’t say anything about using LocalAlloc for memory allocation – is there a technical reason you used LocalAlloc, or is/was it personal preference?

  19. Joe says:

    RE: reinterpret_cast/static_cast – the result of both is unspecified, but in reality they both have the correct effect.

    If you’re a language lawyer type and can’t stand to use an unspecified result, there is a way to do the conversion in an entirely above board way – given a suitably aligned void* use ‘PMIB_IPADDRTABLE piat = new(voidPtr) MIB_IPADDRTABLE;’.

  20. Ken Hagan says:

    Casts up from void* are dangerous because the void* could have originally been anything. Using reinterpret_cast is an accepted idiom for saying "watch out" in this case, even though the language tolerates the alternative idiom of "assuming you are simply casting back to the type it came from".

  21. Fred Thomas says:

    Since you bring up the subject of wireless adapters, here is a question for you. How do you identify which network adapters are wireless and which are fixed? We had this problem a while ago. Essentially we wanted a machine fingerprint which we planned to use, amongst other things, the MAC of the network adapter. However, on a laptop computer, you can never quite be sure which network adapter is first. Sometimes it is the wireless, sometimes the wired one depending on if there is an access point, if wireless is on etc. So our goal was to always use the wired connection.

    We discussed with MSDN support, and they basically didn’t have an answer, so we ended up with an undocumented hack — ugly. Do you know the "correct" way to do this?

  22. Alexandre Grigoriev says:


    There are wireless-specific NDIS OIDs, which only wireless NICs support. Just query the OID list.


    Unlike most other devices, I’m not really sure if an application can really register for sound device removal notification, with RegisterDeviceNotification. Only the applications that use the new core audio APIs can use OnDeviceRemoved callback.

  23. James Schend says:

    Alexandre: I do web dev, so I don’t know all of the details of the Windows API. All I know is that:

    1) It’s certainly possible for apps to compensate for me pulling the USB headset at any random time. World of Warcraft, for example, handles this correctly, although it causes a few dropped frames and a little disk thrashing. (Most other games don’t.)

    2) Despite it being demonstrably possible, most applications screw it up. My "favorite" is a particular media playing application from Microsoft that not only stops playing its media when the USB headset is yanked, but then lies to me in the error message. "No speakers are plugged-in"– liar!

    I have to close and re-open that app every time I either plug, or unplug, the USB headset. If a video game can get it right, you’d think an application that does nothing but play media could too.

    I’m not trying to pick on any particular app, because the problem is so widespread.

    Just… look, if you write a Windows app that uses audio in any capacity, please go down to OfficeMax or Staples, get a cheap $20 USB headset from Logitech, and see what happens to your app when someone hot-swaps it. Make it part of your QA process. Thank you.

  24. Alexandre Grigoriev says:

    @Ken Hagan,

    reinterpret_cast doesn’t say "watch out". It says to the compiler: don’t pay attention, nothing to watch here, I don’t care if I give you an arbitrary crap (even a ‘float’), just take its bits and put them to the pointer, and shut up. If you use reinterpret_cast to cast between float and int, you will get the result you don’t really want.

    static_cast will give a compile error if you try to cast between incompatible types. This is why you should use it.


    Placement ‘new’ is not implicitly defined by the compiler. When one defines it explicitly, it mostly just returns the argument, being thus no better than a static cast.

    I would not say the result of void* to type* cast is unspecified. Otherwise all malloc invocations in all C code in the world would rely on unspecified behavior.

  25. James Schend says:

    Fred, that’s a bad idea for so many reasons. My desktop has 3 network interfaces, one wired, one wireless (built-in) and one wireless (USB). Which MAC do you use?

    Of course, you said you were going to always prefer the wired one… what if my USB interface was wired? Yes they exist, and yes they’re cheap and plentiful. Now what do you do? I could remove it at any second, and your "machine fingerprint" goes out the window.

    Maybe I get a newer USB network interface and swap it in, or maybe I only have one that I shuttle between 4 computers. (Even worse, now I have 4 computers with the same "fingerprint.")

    I don’t know what the "correct" way to do this is, but I imagine it’s along the lines of, "don’t do it."

    Whatever you do, though, please, *please* make it cope with hot-swappable USB hardware! I still can’t even count the number of applications that fail in retarded ways when I unplug my USB headset. (Yes, that’s right application writers: SOUND CARDS CAN BE USB! Get the memo, PLEASE!)

  26. Joe says:

    [I would not say the result of void* to type* cast is unspecified.]

    You would not say that, but the C++ standard does.

    [Otherwise all malloc invocations in all C code in the world would rely on unspecified behavior.]

    How are you using static_cast in C?

    [When one defines it explicitly, it mostly just returns the argument, being thus no better than a static cast.]

    One doesn’t define it explicitly. One’s compiler vendor supplies a header which takes advantage of known implementation defined behaviour to implement it.

  27. Worf says:

    I suppose the simple way of dealing with hotplug audio is treating it as if it can fail.

    Oh, audio playback failed? Close audio device. Reopen, maybe that reset it (does happen). If you don’t talk to a specific audio device but let Windows choose, reopening it should go to the next device.

    If the open fails – oh so sorry, no audio for you.

  28. Drak says:

    @James: I have one of those USB headphones… Never have any problems with it. You know why? I don’t yank it out while I’m using it… Just a thought :P

  29. Jules says:

    The reason for asking for a wireless password twice is that windows isn’t able to verify it: connecting to a WEP network (at least) there’s no readily-spotted difference between what happens when you get your password wrong and what happens when there’s nothing on the network that responds to your packets.

    Fred: How would you cope with a machine with multiple wired networks?  Or none?  You can’t just assume that "the" wired card is somehow magically constant.  My machine, for instance, has several virtual network drivers installed that appear to be wired networks.  One of the driver options, although I don’t use it, is to randomly select the MAC at boot time. Some machines have multiple real wired network cards.  I have a webcam that when plugged in enumerates as a network device.  One of my machines around here doesn’t have a wired network interface, it only has wireless. How would you stop all these things changing your machine fingerprint?

  30. Ken Hagan says:

    "reinterpret_cast doesn’t say "watch out"."

    It does to me, but then again…

    "It says to the compiler: don’t pay attention, nothing to watch here, "

    …I’m not a compiler. Sorry if the target of the "watch out" wasn’t clear. :)

  31. Jules says:

    Joe: "[I would not say the result of void* to type* cast is unspecified.]

    You would not say that, but the C++ standard does."

    No, it doesn’t.  It’s much more complicated than that.  Specifically, it gives two instances where the results are specified:

    "The null pointer value is converted to the null pointer value of the destination type."


    "A value of type pointer to object converted to pointer to cv void and back, possibly with different cv-qualification, shall have its original value."

    It gives an example of the latter:

    T* p1 = new T;

    const T* p2 = static_cast<const T*>(static_cast<void*>(p1));

    bool b = p1 == p2; // b will have the value true.

  32. Florin Teodorescu says:

    … and actually to give some more historical facts on the actual title of the blog ("Why does the wireless connection dialog ask for your password twice?"), remember the context in which this annoying little "feature" came to be?

    In Windows XP it was not there. You could merely enter the WEP key in clear. It was introduced around the XP SP2 time frame.

    Remember what was special about XP SP2? Big emphasis on security. Well, with this bias, we were pretty acceptant to much of the users complaints touching or seeming to come from a security / privacy side. Believe it or not, there were actually user complaints indicating that entering the WEP key should not be in clear.


    @JJJ (Apr 19 12:30p): No, this was not driven by stubborn stickines to dry specs but a case in which pulling the blanket on one end you uncover the other – all good intentions throughout :-). However we live in a changing world and you saw this corrected in the next releases..

    @Gabe (Apr 19 1:09p): When considering that "feature" actually the scenario was considered to be a password configuration one. Remember, you are expected to enter the WEP key only once, when you connect the first time to the network and not each and every time you get in range.

    @Random832 (Apr 20 4:20a): I am not sure I agree. Entering the WEP key is not similar to when you login. It is similar to when you configure say your email account in your client of choice and you enter the account’s password for the very first time (see above).

  33. Florin Teodorescu says:

    As one privy to the (XP) Wireless Zero Configuration service (WZC), I can answer some of the questions and hopefully demistify some of the unknowns:

    Re: "(Theory: The wireless zero configuration service saw another access point and said, "Hey, that access point over there looks much nicer than then one I’m currently connected to. I’m going to drop my current connection and see if maybe that other access point will go out with me." And then it went up to that other access point and asked it out on a date. When the other access point said no, it came crawling back to the original access point. Repeat.)"

    Actually: WZC was never that dumb. According to the initial requirements, WZC had to cover a case that in the early days of wireless connections was deemed to be common and important to solve: seamless connectivity switch betweeen overlapping networks (think different SSIDs, not Access Points). More specifically: you have a subscription to network A you want to use, but happen to be in the coverage of the paid network B. Your configuration includes both network A and B, in this priority order and you are merely connected to B. As you move into an area where A becomes available, while still under the coverage of network B, as per WZC requirements, connection was expected to switch automatically to network A.This is where the "Z" in WZC came from (*zero* configuration).

    Now in order to cover this functionality, first WZC configured the wireless NIC with all the settings needed for connecting and holding the connection to network B. Then, every once in a while (1min) two commands were issued to the NIC driver:

    1) – "scan the environment for new wireless beacons"

    2) – "give me the list of beacons detected".

    With these two answered, WZC can make the decision to switch if any better network is available, but if not, no further action was taken and the wireless driver was left untouched with the same settings that were expected to hold the connection to network B active and well.

    The ability to scan the environment while retaining the connection to some network was a requirement on the driver implementer, specified in the IEEE 802.11 spec, and WZC was making use of it.

    Reallity is that in those early days implementing correctly such behavior at NIC driver level was challenging. The driver had to put shortly on hold the current connection while using the radio to scan all channels. Depending on the NIC manufacturer and driver developer, having the connection dropped in this process was fairly common. When such thing happened, once scan completed, the NIC automatically reattached to the network for which it was configured. Everything happened under the hood, WZC didn’t have any action to take and this is the reason why the "constant dropping connection" was only happening for some and not for others – all depending on the kind of wireless NIC and driver you had.

    With the facts right, now you can see why the approach described in this blog solves the problem: once you have the connection set, as you stop WZC there is no software component asking for a periodic rescan, hence the driver is not asked to do what it should do and doesn’t do well, so the connection is retained. However, along with that you loose the functionality described above (seamless switch to the more preferred network) for which the scan was intended. But of course, time proved that’s a feature not as common as thought..

Comments are closed.