{"id":14303,"date":"2010-04-19T07:00:00","date_gmt":"2010-04-19T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2010\/04\/19\/why-does-the-wireless-connection-dialog-ask-for-your-password-twice\/"},"modified":"2010-04-19T07:00:00","modified_gmt":"2010-04-19T07:00:00","slug":"why-does-the-wireless-connection-dialog-ask-for-your-password-twice","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20100419-00\/?p=14303","title":{"rendered":"Why does the wireless connection dialog ask for your password twice?"},"content":{"rendered":"<p>\nMartin wonders\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/pages\/407234.aspx#1239342\">\nwhy the wireless networking dialog asks you to type your password twice<\/a>\nwhen connecting to an existing network.\n<\/p>\n<p>\nYeah, that bothers me too, and I don&#8217;t know why either.\n<\/p>\n<p>\nBut while we&#8217;re on the topic of wireless networking,\nI thought I&#8217;d share a little program that is just as useless\nas my answer above.\n(If other people get to hijack the topic, then I want to also.)\n<\/p>\n<p>\nBack in the early days of Windows&nbsp;XP, I found that my\nwireless networking adapter would constantly disconnect and\nreconnect.\nI never figured out why, but I did have a theory.\n(Theory:\nThe wireless zero configuration service saw another access point\nand said,\n&#8220;Hey, that access point over there looks much nicer than then\none I&#8217;m currently connected to.\nI&#8217;m going to drop my current connection and see if maybe that other\naccess point will go out with me.&#8221;\nAnd then it went up to that other access point and asked it out\non a date.\nWhen the other access point said no, it came crawling back to the\noriginal access point.\nRepeat.)\n<\/p>\n<p>\nAnyway, to avoid this problem\n(which went away after a while for reasons unclear;\nmaybe it was fixed, maybe whatever situation triggered the problem\nwent away, I didn&#8217;t bother investigating),\nI wrote a program which did two very simple things:\n<\/p>\n<ol>\n<li>If the wireless networking adapter was connected to an access\n    point, then turn off the wireless zero configuration service.<\/p>\n<li>If the wireless networking adapter was not connected to an access\n    point, then turn on the wireless zero configuration service.\n<\/ol>\n<p>\nIn other words, it automates the process described\n<a HREF=\"http:\/\/www.wi-fiplanet.com\/tutorials\/article.php\/3573316\">\non this Web page<\/a>.\n(I like how that article was\n<a HREF=\"http:\/\/cws.internet.com\/article\/3115-4447.htm\">\ncopied in its entirety<\/a> to another site, which replaced the author&#8217;s\nname. Now that&#8217;s chutzpah.)\n<\/p>\n<p>\nMind you,\nthe program really is no longer interesting in and of itself\nany more because the underlying\nproblem went away, but I thought it could serve as an\nillustration of how you can put together some simple things to make\na useful tool.\n<\/p>\n<p>\nFirst, I changed the security descriptor on the wireless zero\nconfiguration service so that my account had permission to turn it on\nand off.\n<\/p>\n<p>\nSecond, I added this code to\na program that hangs out my Startup group which monitors various things\nI like to monitor.\n(I have one program that monitors several things just to cut down on the\nnumber of processes hanging around on my machine.)\nThe code has been compressed and reformatted to get rid of the uninteresting\nparts.\n<\/p>\n<pre>\nclass MonitorWireless\n{\npublic:\n  MonitorWireless()\n    : m_hWait(NULL)\n  {\n      ZeroMemory(&amp;m_o, sizeof(m_o));\n  }\n  ~MonitorWireless()\n  {\n    if (m_hWait) UnregisterWaitEx(m_hWait, INVALID_HANDLE_VALUE);\n    if (m_o.hEvent) CloseHandle(m_o.hEvent);\n  }\n  BOOL Initialize();\nprotected:\n  static void CALLBACK s_OnChange(PVOID lpParameter, BOOLEAN)\n  {\n    MonitorWireless *self =\n               reinterpret_cast&lt;MonitorWireless*&gt;(lpParameter);\n    self-&gt;CheckIPAddress(); \/\/ something changed - check it again\n  }\n  void CheckIPAddress();\n  static void StartStopService(BOOL fStart);\nprivate:\n    HANDLE m_hWait;\n    OVERLAPPED m_o;\n}\n<\/pre>\n<p>\nThe class definition is all very boring.\nOur class has an <code>OVERLAPPED<\/code> structure which we use\nto register for IP address change notifications, and it has a\nhandle to a registered wait, which takes advantage of the thread\npool to reduce the number of threads used by the process.\n<\/p>\n<pre>\nBOOL MonitorWireless::Initialize()\n{\n  m_o.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\n  if (!m_o.hEvent) return FALSE;\n  if (!RegisterWaitForSingleObject(&amp;m_hWait, m_o.hEvent,\n                      s_OnChange, this, INFINITE, 0)) return FALSE;\n  CheckIPAddress();\n  return TRUE;\n}\n<\/pre>\n<p>\nWhen the object is initialized, it creates the handle that we will\nask to be set whenever the computer&#8217;s IP address changes, and\nthen registers a wait on that handle with a callback function.\nWhen the event is signaled, we check the IP address.\nAnd to start the ball rolling, we check the IP address at\ninitialization.\n<\/p>\n<pre>\nvoid MonitorWireless::CheckIPAddress()\n{\n  ULONG ulSize = 0;\n  if (GetIpAddrTable(NULL, &amp;ulSize, 0) ==\n                                     ERROR_INSUFFICIENT_BUFFER) {\n    PMIB_IPADDRTABLE piat = reinterpret_cast&lt;PMIB_IPADDRTABLE&gt;\n                                (LocalAlloc(LMEM_FIXED, ulSize));\n    if (piat) {\n      if (GetIpAddrTable(piat, &amp;ulSize, 0) == ERROR_SUCCESS) {\n        BOOL fFound = FALSE;\n        for (DWORD dwIndex = 0; dwIndex &lt; piat-&gt;dwNumEntries;\n             dwIndex++) {\n          PMIB_IPADDRROW prow = &amp;piat-&gt;table[dwIndex];\n          if (prow-&gt;dwAddr == 0) continue;\n          if ((prow-&gt;wType &amp; (MIB_IPADDR_DYNAMIC |\n                              MIB_IPADDR_DELETED |\n                              MIB_IPADDR_DISCONNECTED)) !=\n                              MIB_IPADDR_DYNAMIC) continue;\n          fFound = TRUE;\n          break;\n        }\n        StartStopService(!fFound);\n      }\n      LocalFree(piat);\n    }\n  }\n  HANDLE h;\n  NotifyAddrChange(&amp;h, &amp;m_o);\n}\n<\/pre>\n<p>\nWe start by getting the IP address table (doing the standard two-step\nof first asking how much memory we need to hold it, allocating the memory,\nand then filling the buffer) and walking through each IP address.\nIf we find an entry with an IP address that is dynamic,\nnot deleted, and not disconnected, then we declare ourselves happy;\notherwise we are sad.\nIf we are happy, then we stop the wireless zero configuration service;\nif we are sad, then we start it.\n<\/p>\n<pre>\nvoid MonitorWireless::StartStopService(BOOL fStart)\n{\n  SC_HANDLE sc;\n  sc = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT |\n                                 SC_MANAGER_ENUMERATE_SERVICE);\n  if (sc) {\n    SC_HANDLE scWzcsvc = OpenService(sc, TEXT(\"wzcsvc\"),\n                   fStart ? SERVICE_START\n                          : SERVICE_STOP | SERVICE_QUERY_STATUS);\n    if (scWzcsvc) {\n      if (fStart) StartService(scWzcsvc, 0, NULL);\n      else        StopService(scWzcsvc);\n      CloseServiceHandle(scWzcsvc);\n    }\n    CloseServiceHandle(sc);\n  }\n}\n<\/pre>\n<p>\nTo start or stop the service, we first connect to the service\ncontrol manager, open the service we want to start\/stop,\nand then, well, start or stop it.\n<\/p>\n<p>\nThere is already a <code>Start&shy;Service<\/code> function,\nbut no <code>Stop&shy;Service<\/code> function, so I wrote my own:<\/p>\n<pre>\nvoid StopService(SC_HANDLE sc)\n{\n SERVICE_STATUS ss;\n if (QueryServiceStatus(sc, &amp;ss) &amp;&amp;\n     ss.dwCurrentState != SERVICE_STOPPED &amp;&amp;\n     ss.dwCurrentState != SERVICE_STOP_PENDING)\n   ControlService(sc, SERVICE_CONTROL_STOP, &amp;ss);\n}\n<\/pre>\n<p>\nIf the service is not already stopped (or stopping),\nthen we tell it to stop.\n<\/p>\n<p>\nAnd there you have it, a program that you don&#8217;t need any more.\nBut the point here was more to show how you can put together\nsome basic elements to solve a simple problem.\n<\/p>\n<p>\nTechniques illustrated:\n<\/p>\n<ul>\n<li>Registering a wait in the thread pool.\n<li>Registering asynchronously for IP address changes.\n<li>Starting and stopping a service.\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>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&#8217;t know why either. But while we&#8217;re on the topic of wireless networking, I thought I&#8217;d share a little program that is just as useless as my answer [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[26],"class_list":["post-14303","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>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&#8217;t know why either. But while we&#8217;re on the topic of wireless networking, I thought I&#8217;d share a little program that is just as useless as my answer [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/14303","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=14303"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/14303\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=14303"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=14303"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=14303"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}