(root)/
Python-3.12.0/
Lib/
test/
test_winreg.py
       1  # Test the windows specific win32reg module.
       2  # Only win32reg functions not hit here: FlushKey, LoadKey and SaveKey
       3  
       4  import gc
       5  import os, sys, errno
       6  import threading
       7  import unittest
       8  from platform import machine, win32_edition
       9  from test.support import cpython_only, import_helper
      10  
      11  # Do this first so test will be skipped if module doesn't exist
      12  import_helper.import_module('winreg', required_on=['win'])
      13  # Now import everything
      14  from winreg import *
      15  
      16  try:
      17      REMOTE_NAME = sys.argv[sys.argv.index("--remote")+1]
      18  except (IndexError, ValueError):
      19      REMOTE_NAME = None
      20  
      21  # tuple of (major, minor)
      22  WIN_VER = sys.getwindowsversion()[:2]
      23  # Some tests should only run on 64-bit architectures where WOW64 will be.
      24  WIN64_MACHINE = True if machine() == "AMD64" else False
      25  
      26  # Starting with Windows 7 and Windows Server 2008 R2, WOW64 no longer uses
      27  # registry reflection and formerly reflected keys are shared instead.
      28  # Windows 7 and Windows Server 2008 R2 are version 6.1. Due to this, some
      29  # tests are only valid up until 6.1
      30  HAS_REFLECTION = True if WIN_VER < (6, 1) else False
      31  
      32  # Use a per-process key to prevent concurrent test runs (buildbot!) from
      33  # stomping on each other.
      34  test_key_base = "Python Test Key [%d] - Delete Me" % (os.getpid(),)
      35  test_key_name = "SOFTWARE\\" + test_key_base
      36  # On OS'es that support reflection we should test with a reflected key
      37  test_reflect_key_name = "SOFTWARE\\Classes\\" + test_key_base
      38  
      39  test_data = [
      40      ("Int Value",     45,                                      REG_DWORD),
      41      ("Qword Value",   0x1122334455667788,                      REG_QWORD),
      42      ("String Val",    "A string value",                        REG_SZ),
      43      ("StringExpand",  "The path is %path%",                    REG_EXPAND_SZ),
      44      ("Multi-string",  ["Lots", "of", "string", "values"],      REG_MULTI_SZ),
      45      ("Multi-nul",     ["", "", "", ""],                        REG_MULTI_SZ),
      46      ("Raw Data",      b"binary\x00data",                       REG_BINARY),
      47      ("Big String",    "x"*(2**14-1),                           REG_SZ),
      48      ("Big Binary",    b"x"*(2**14),                            REG_BINARY),
      49      # Two and three kanjis, meaning: "Japan" and "Japanese".
      50      ("Japanese 日本", "日本語", REG_SZ),
      51  ]
      52  
      53  
      54  @cpython_only
      55  class ESC[4;38;5;81mHeapTypeTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      56      def test_have_gc(self):
      57          self.assertTrue(gc.is_tracked(HKEYType))
      58  
      59      def test_immutable(self):
      60          with self.assertRaisesRegex(TypeError, "immutable"):
      61              HKEYType.foo = "bar"
      62  
      63  
      64  class ESC[4;38;5;81mBaseWinregTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      65  
      66      def setUp(self):
      67          # Make sure that the test key is absent when the test
      68          # starts.
      69          self.delete_tree(HKEY_CURRENT_USER, test_key_name)
      70  
      71      def delete_tree(self, root, subkey):
      72          try:
      73              hkey = OpenKey(root, subkey, 0, KEY_ALL_ACCESS)
      74          except OSError:
      75              # subkey does not exist
      76              return
      77          while True:
      78              try:
      79                  subsubkey = EnumKey(hkey, 0)
      80              except OSError:
      81                  # no more subkeys
      82                  break
      83              self.delete_tree(hkey, subsubkey)
      84          CloseKey(hkey)
      85          DeleteKey(root, subkey)
      86  
      87      def _write_test_data(self, root_key, subkeystr="sub_key",
      88                           CreateKey=CreateKey):
      89          # Set the default value for this key.
      90          SetValue(root_key, test_key_name, REG_SZ, "Default value")
      91          key = CreateKey(root_key, test_key_name)
      92          self.assertTrue(key.handle != 0)
      93          # Create a sub-key
      94          sub_key = CreateKey(key, subkeystr)
      95          # Give the sub-key some named values
      96  
      97          for value_name, value_data, value_type in test_data:
      98              SetValueEx(sub_key, value_name, 0, value_type, value_data)
      99  
     100          # Check we wrote as many items as we thought.
     101          nkeys, nvalues, since_mod = QueryInfoKey(key)
     102          self.assertEqual(nkeys, 1, "Not the correct number of sub keys")
     103          self.assertEqual(nvalues, 1, "Not the correct number of values")
     104          nkeys, nvalues, since_mod = QueryInfoKey(sub_key)
     105          self.assertEqual(nkeys, 0, "Not the correct number of sub keys")
     106          self.assertEqual(nvalues, len(test_data),
     107                           "Not the correct number of values")
     108          # Close this key this way...
     109          # (but before we do, copy the key as an integer - this allows
     110          # us to test that the key really gets closed).
     111          int_sub_key = int(sub_key)
     112          CloseKey(sub_key)
     113          try:
     114              QueryInfoKey(int_sub_key)
     115              self.fail("It appears the CloseKey() function does "
     116                        "not close the actual key!")
     117          except OSError:
     118              pass
     119          # ... and close that key that way :-)
     120          int_key = int(key)
     121          key.Close()
     122          try:
     123              QueryInfoKey(int_key)
     124              self.fail("It appears the key.Close() function "
     125                        "does not close the actual key!")
     126          except OSError:
     127              pass
     128      def _read_test_data(self, root_key, subkeystr="sub_key", OpenKey=OpenKey):
     129          # Check we can get default value for this key.
     130          val = QueryValue(root_key, test_key_name)
     131          self.assertEqual(val, "Default value",
     132                           "Registry didn't give back the correct value")
     133  
     134          key = OpenKey(root_key, test_key_name)
     135          # Read the sub-keys
     136          with OpenKey(key, subkeystr) as sub_key:
     137              # Check I can enumerate over the values.
     138              index = 0
     139              while 1:
     140                  try:
     141                      data = EnumValue(sub_key, index)
     142                  except OSError:
     143                      break
     144                  self.assertEqual(data in test_data, True,
     145                                   "Didn't read back the correct test data")
     146                  index = index + 1
     147              self.assertEqual(index, len(test_data),
     148                               "Didn't read the correct number of items")
     149              # Check I can directly access each item
     150              for value_name, value_data, value_type in test_data:
     151                  read_val, read_typ = QueryValueEx(sub_key, value_name)
     152                  self.assertEqual(read_val, value_data,
     153                                   "Could not directly read the value")
     154                  self.assertEqual(read_typ, value_type,
     155                                   "Could not directly read the value")
     156          sub_key.Close()
     157          # Enumerate our main key.
     158          read_val = EnumKey(key, 0)
     159          self.assertEqual(read_val, subkeystr, "Read subkey value wrong")
     160          try:
     161              EnumKey(key, 1)
     162              self.fail("Was able to get a second key when I only have one!")
     163          except OSError:
     164              pass
     165  
     166          key.Close()
     167  
     168      def _delete_test_data(self, root_key, subkeystr="sub_key"):
     169          key = OpenKey(root_key, test_key_name, 0, KEY_ALL_ACCESS)
     170          sub_key = OpenKey(key, subkeystr, 0, KEY_ALL_ACCESS)
     171          # It is not necessary to delete the values before deleting
     172          # the key (although subkeys must not exist).  We delete them
     173          # manually just to prove we can :-)
     174          for value_name, value_data, value_type in test_data:
     175              DeleteValue(sub_key, value_name)
     176  
     177          nkeys, nvalues, since_mod = QueryInfoKey(sub_key)
     178          self.assertEqual(nkeys, 0, "subkey not empty before delete")
     179          self.assertEqual(nvalues, 0, "subkey not empty before delete")
     180          sub_key.Close()
     181          DeleteKey(key, subkeystr)
     182  
     183          try:
     184              # Shouldn't be able to delete it twice!
     185              DeleteKey(key, subkeystr)
     186              self.fail("Deleting the key twice succeeded")
     187          except OSError:
     188              pass
     189          key.Close()
     190          DeleteKey(root_key, test_key_name)
     191          # Opening should now fail!
     192          try:
     193              key = OpenKey(root_key, test_key_name)
     194              self.fail("Could open the non-existent key")
     195          except OSError: # Use this error name this time
     196              pass
     197  
     198      def _test_all(self, root_key, subkeystr="sub_key"):
     199          self._write_test_data(root_key, subkeystr)
     200          self._read_test_data(root_key, subkeystr)
     201          self._delete_test_data(root_key, subkeystr)
     202  
     203      def _test_named_args(self, key, sub_key):
     204          with CreateKeyEx(key=key, sub_key=sub_key, reserved=0,
     205                           access=KEY_ALL_ACCESS) as ckey:
     206              self.assertTrue(ckey.handle != 0)
     207  
     208          with OpenKeyEx(key=key, sub_key=sub_key, reserved=0,
     209                         access=KEY_ALL_ACCESS) as okey:
     210              self.assertTrue(okey.handle != 0)
     211  
     212  
     213  class ESC[4;38;5;81mLocalWinregTests(ESC[4;38;5;149mBaseWinregTests):
     214  
     215      def test_registry_works(self):
     216          self._test_all(HKEY_CURRENT_USER)
     217          self._test_all(HKEY_CURRENT_USER, "日本-subkey")
     218  
     219      def test_registry_works_extended_functions(self):
     220          # Substitute the regular CreateKey and OpenKey calls with their
     221          # extended counterparts.
     222          # Note: DeleteKeyEx is not used here because it is platform dependent
     223          cke = lambda key, sub_key: CreateKeyEx(key, sub_key, 0, KEY_ALL_ACCESS)
     224          self._write_test_data(HKEY_CURRENT_USER, CreateKey=cke)
     225  
     226          oke = lambda key, sub_key: OpenKeyEx(key, sub_key, 0, KEY_READ)
     227          self._read_test_data(HKEY_CURRENT_USER, OpenKey=oke)
     228  
     229          self._delete_test_data(HKEY_CURRENT_USER)
     230  
     231      def test_named_arguments(self):
     232          self._test_named_args(HKEY_CURRENT_USER, test_key_name)
     233          # Use the regular DeleteKey to clean up
     234          # DeleteKeyEx takes named args and is tested separately
     235          DeleteKey(HKEY_CURRENT_USER, test_key_name)
     236  
     237      def test_connect_registry_to_local_machine_works(self):
     238          # perform minimal ConnectRegistry test which just invokes it
     239          h = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
     240          self.assertNotEqual(h.handle, 0)
     241          h.Close()
     242          self.assertEqual(h.handle, 0)
     243  
     244      def test_nonexistent_remote_registry(self):
     245          connect = lambda: ConnectRegistry("abcdefghijkl", HKEY_CURRENT_USER)
     246          self.assertRaises(OSError, connect)
     247  
     248      def testExpandEnvironmentStrings(self):
     249          r = ExpandEnvironmentStrings("%windir%\\test")
     250          self.assertEqual(type(r), str)
     251          self.assertEqual(r, os.environ["windir"] + "\\test")
     252  
     253      def test_context_manager(self):
     254          # ensure that the handle is closed if an exception occurs
     255          try:
     256              with ConnectRegistry(None, HKEY_LOCAL_MACHINE) as h:
     257                  self.assertNotEqual(h.handle, 0)
     258                  raise OSError
     259          except OSError:
     260              self.assertEqual(h.handle, 0)
     261  
     262      def test_changing_value(self):
     263          # Issue2810: A race condition in 2.6 and 3.1 may cause
     264          # EnumValue or QueryValue to raise "WindowsError: More data is
     265          # available"
     266          done = False
     267  
     268          class ESC[4;38;5;81mVeryActiveThread(ESC[4;38;5;149mthreadingESC[4;38;5;149m.ESC[4;38;5;149mThread):
     269              def run(self):
     270                  with CreateKey(HKEY_CURRENT_USER, test_key_name) as key:
     271                      use_short = True
     272                      long_string = 'x'*2000
     273                      while not done:
     274                          s = 'x' if use_short else long_string
     275                          use_short = not use_short
     276                          SetValue(key, 'changing_value', REG_SZ, s)
     277  
     278          thread = VeryActiveThread()
     279          thread.start()
     280          try:
     281              with CreateKey(HKEY_CURRENT_USER,
     282                             test_key_name+'\\changing_value') as key:
     283                  for _ in range(1000):
     284                      num_subkeys, num_values, t = QueryInfoKey(key)
     285                      for i in range(num_values):
     286                          name = EnumValue(key, i)
     287                          QueryValue(key, name[0])
     288          finally:
     289              done = True
     290              thread.join()
     291              DeleteKey(HKEY_CURRENT_USER, test_key_name+'\\changing_value')
     292              DeleteKey(HKEY_CURRENT_USER, test_key_name)
     293  
     294      def test_long_key(self):
     295          # Issue2810, in 2.6 and 3.1 when the key name was exactly 256
     296          # characters, EnumKey raised "WindowsError: More data is
     297          # available"
     298          name = 'x'*256
     299          try:
     300              with CreateKey(HKEY_CURRENT_USER, test_key_name) as key:
     301                  SetValue(key, name, REG_SZ, 'x')
     302                  num_subkeys, num_values, t = QueryInfoKey(key)
     303                  EnumKey(key, 0)
     304          finally:
     305              DeleteKey(HKEY_CURRENT_USER, '\\'.join((test_key_name, name)))
     306              DeleteKey(HKEY_CURRENT_USER, test_key_name)
     307  
     308      def test_dynamic_key(self):
     309          # Issue2810, when the value is dynamically generated, these
     310          # raise "WindowsError: More data is available" in 2.6 and 3.1
     311          try:
     312              EnumValue(HKEY_PERFORMANCE_DATA, 0)
     313          except OSError as e:
     314              if e.errno in (errno.EPERM, errno.EACCES):
     315                  self.skipTest("access denied to registry key "
     316                                "(are you running in a non-interactive session?)")
     317              raise
     318          QueryValueEx(HKEY_PERFORMANCE_DATA, "")
     319  
     320      # Reflection requires XP x64/Vista at a minimum. XP doesn't have this stuff
     321      # or DeleteKeyEx so make sure their use raises NotImplementedError
     322      @unittest.skipUnless(WIN_VER < (5, 2), "Requires Windows XP")
     323      def test_reflection_unsupported(self):
     324          try:
     325              with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
     326                  self.assertNotEqual(ck.handle, 0)
     327  
     328              key = OpenKey(HKEY_CURRENT_USER, test_key_name)
     329              self.assertNotEqual(key.handle, 0)
     330  
     331              with self.assertRaises(NotImplementedError):
     332                  DisableReflectionKey(key)
     333              with self.assertRaises(NotImplementedError):
     334                  EnableReflectionKey(key)
     335              with self.assertRaises(NotImplementedError):
     336                  QueryReflectionKey(key)
     337              with self.assertRaises(NotImplementedError):
     338                  DeleteKeyEx(HKEY_CURRENT_USER, test_key_name)
     339          finally:
     340              DeleteKey(HKEY_CURRENT_USER, test_key_name)
     341  
     342      def test_setvalueex_value_range(self):
     343          # Test for Issue #14420, accept proper ranges for SetValueEx.
     344          # Py2Reg, which gets called by SetValueEx, was using PyLong_AsLong,
     345          # thus raising OverflowError. The implementation now uses
     346          # PyLong_AsUnsignedLong to match DWORD's size.
     347          try:
     348              with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
     349                  self.assertNotEqual(ck.handle, 0)
     350                  SetValueEx(ck, "test_name", None, REG_DWORD, 0x80000000)
     351          finally:
     352              DeleteKey(HKEY_CURRENT_USER, test_key_name)
     353  
     354      def test_setvalueex_negative_one_check(self):
     355          # Test for Issue #43984, check -1 was not set by SetValueEx.
     356          # Py2Reg, which gets called by SetValueEx, wasn't checking return
     357          # value by PyLong_AsUnsignedLong, thus setting -1 as value in the registry.
     358          # The implementation now checks PyLong_AsUnsignedLong return value to assure
     359          # the value set was not -1.
     360          try:
     361              with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
     362                  with self.assertRaises(OverflowError):
     363                      SetValueEx(ck, "test_name_dword", None, REG_DWORD, -1)
     364                      SetValueEx(ck, "test_name_qword", None, REG_QWORD, -1)
     365                  self.assertRaises(FileNotFoundError, QueryValueEx, ck, "test_name_dword")
     366                  self.assertRaises(FileNotFoundError, QueryValueEx, ck, "test_name_qword")
     367  
     368          finally:
     369              DeleteKey(HKEY_CURRENT_USER, test_key_name)
     370  
     371      def test_queryvalueex_return_value(self):
     372          # Test for Issue #16759, return unsigned int from QueryValueEx.
     373          # Reg2Py, which gets called by QueryValueEx, was returning a value
     374          # generated by PyLong_FromLong. The implementation now uses
     375          # PyLong_FromUnsignedLong to match DWORD's size.
     376          try:
     377              with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
     378                  self.assertNotEqual(ck.handle, 0)
     379                  test_val = 0x80000000
     380                  SetValueEx(ck, "test_name", None, REG_DWORD, test_val)
     381                  ret_val, ret_type = QueryValueEx(ck, "test_name")
     382                  self.assertEqual(ret_type, REG_DWORD)
     383                  self.assertEqual(ret_val, test_val)
     384          finally:
     385              DeleteKey(HKEY_CURRENT_USER, test_key_name)
     386  
     387      def test_setvalueex_crash_with_none_arg(self):
     388          # Test for Issue #21151, segfault when None is passed to SetValueEx
     389          try:
     390              with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
     391                  self.assertNotEqual(ck.handle, 0)
     392                  test_val = None
     393                  SetValueEx(ck, "test_name", 0, REG_BINARY, test_val)
     394                  ret_val, ret_type = QueryValueEx(ck, "test_name")
     395                  self.assertEqual(ret_type, REG_BINARY)
     396                  self.assertEqual(ret_val, test_val)
     397          finally:
     398              DeleteKey(HKEY_CURRENT_USER, test_key_name)
     399  
     400      def test_read_string_containing_null(self):
     401          # Test for issue 25778: REG_SZ should not contain null characters
     402          try:
     403              with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
     404                  self.assertNotEqual(ck.handle, 0)
     405                  test_val = "A string\x00 with a null"
     406                  SetValueEx(ck, "test_name", 0, REG_SZ, test_val)
     407                  ret_val, ret_type = QueryValueEx(ck, "test_name")
     408                  self.assertEqual(ret_type, REG_SZ)
     409                  self.assertEqual(ret_val, "A string")
     410          finally:
     411              DeleteKey(HKEY_CURRENT_USER, test_key_name)
     412  
     413  
     414  @unittest.skipUnless(REMOTE_NAME, "Skipping remote registry tests")
     415  class ESC[4;38;5;81mRemoteWinregTests(ESC[4;38;5;149mBaseWinregTests):
     416  
     417      def test_remote_registry_works(self):
     418          remote_key = ConnectRegistry(REMOTE_NAME, HKEY_CURRENT_USER)
     419          self._test_all(remote_key)
     420  
     421  
     422  @unittest.skipUnless(WIN64_MACHINE, "x64 specific registry tests")
     423  class ESC[4;38;5;81mWin64WinregTests(ESC[4;38;5;149mBaseWinregTests):
     424  
     425      def test_named_arguments(self):
     426          self._test_named_args(HKEY_CURRENT_USER, test_key_name)
     427          # Clean up and also exercise the named arguments
     428          DeleteKeyEx(key=HKEY_CURRENT_USER, sub_key=test_key_name,
     429                      access=KEY_ALL_ACCESS, reserved=0)
     430  
     431      @unittest.skipIf(win32_edition() in ('WindowsCoreHeadless', 'IoTEdgeOS'), "APIs not available on WindowsCoreHeadless")
     432      def test_reflection_functions(self):
     433          # Test that we can call the query, enable, and disable functions
     434          # on a key which isn't on the reflection list with no consequences.
     435          with OpenKey(HKEY_LOCAL_MACHINE, "Software") as key:
     436              # HKLM\Software is redirected but not reflected in all OSes
     437              self.assertTrue(QueryReflectionKey(key))
     438              self.assertIsNone(EnableReflectionKey(key))
     439              self.assertIsNone(DisableReflectionKey(key))
     440              self.assertTrue(QueryReflectionKey(key))
     441  
     442      @unittest.skipUnless(HAS_REFLECTION, "OS doesn't support reflection")
     443      def test_reflection(self):
     444          # Test that we can create, open, and delete keys in the 32-bit
     445          # area. Because we are doing this in a key which gets reflected,
     446          # test the differences of 32 and 64-bit keys before and after the
     447          # reflection occurs (ie. when the created key is closed).
     448          try:
     449              with CreateKeyEx(HKEY_CURRENT_USER, test_reflect_key_name, 0,
     450                               KEY_ALL_ACCESS | KEY_WOW64_32KEY) as created_key:
     451                  self.assertNotEqual(created_key.handle, 0)
     452  
     453                  # The key should now be available in the 32-bit area
     454                  with OpenKey(HKEY_CURRENT_USER, test_reflect_key_name, 0,
     455                               KEY_ALL_ACCESS | KEY_WOW64_32KEY) as key:
     456                      self.assertNotEqual(key.handle, 0)
     457  
     458                  # Write a value to what currently is only in the 32-bit area
     459                  SetValueEx(created_key, "", 0, REG_SZ, "32KEY")
     460  
     461                  # The key is not reflected until created_key is closed.
     462                  # The 64-bit version of the key should not be available yet.
     463                  open_fail = lambda: OpenKey(HKEY_CURRENT_USER,
     464                                              test_reflect_key_name, 0,
     465                                              KEY_READ | KEY_WOW64_64KEY)
     466                  self.assertRaises(OSError, open_fail)
     467  
     468              # Now explicitly open the 64-bit version of the key
     469              with OpenKey(HKEY_CURRENT_USER, test_reflect_key_name, 0,
     470                           KEY_ALL_ACCESS | KEY_WOW64_64KEY) as key:
     471                  self.assertNotEqual(key.handle, 0)
     472                  # Make sure the original value we set is there
     473                  self.assertEqual("32KEY", QueryValue(key, ""))
     474                  # Set a new value, which will get reflected to 32-bit
     475                  SetValueEx(key, "", 0, REG_SZ, "64KEY")
     476  
     477              # Reflection uses a "last-writer wins policy, so the value we set
     478              # on the 64-bit key should be the same on 32-bit
     479              with OpenKey(HKEY_CURRENT_USER, test_reflect_key_name, 0,
     480                           KEY_READ | KEY_WOW64_32KEY) as key:
     481                  self.assertEqual("64KEY", QueryValue(key, ""))
     482          finally:
     483              DeleteKeyEx(HKEY_CURRENT_USER, test_reflect_key_name,
     484                          KEY_WOW64_32KEY, 0)
     485  
     486      @unittest.skipUnless(HAS_REFLECTION, "OS doesn't support reflection")
     487      def test_disable_reflection(self):
     488          # Make use of a key which gets redirected and reflected
     489          try:
     490              with CreateKeyEx(HKEY_CURRENT_USER, test_reflect_key_name, 0,
     491                               KEY_ALL_ACCESS | KEY_WOW64_32KEY) as created_key:
     492                  # QueryReflectionKey returns whether or not the key is disabled
     493                  disabled = QueryReflectionKey(created_key)
     494                  self.assertEqual(type(disabled), bool)
     495                  # HKCU\Software\Classes is reflected by default
     496                  self.assertFalse(disabled)
     497  
     498                  DisableReflectionKey(created_key)
     499                  self.assertTrue(QueryReflectionKey(created_key))
     500  
     501              # The key is now closed and would normally be reflected to the
     502              # 64-bit area, but let's make sure that didn't happen.
     503              open_fail = lambda: OpenKeyEx(HKEY_CURRENT_USER,
     504                                            test_reflect_key_name, 0,
     505                                            KEY_READ | KEY_WOW64_64KEY)
     506              self.assertRaises(OSError, open_fail)
     507  
     508              # Make sure the 32-bit key is actually there
     509              with OpenKeyEx(HKEY_CURRENT_USER, test_reflect_key_name, 0,
     510                             KEY_READ | KEY_WOW64_32KEY) as key:
     511                  self.assertNotEqual(key.handle, 0)
     512          finally:
     513              DeleteKeyEx(HKEY_CURRENT_USER, test_reflect_key_name,
     514                          KEY_WOW64_32KEY, 0)
     515  
     516      def test_exception_numbers(self):
     517          with self.assertRaises(FileNotFoundError) as ctx:
     518              QueryValue(HKEY_CLASSES_ROOT, 'some_value_that_does_not_exist')
     519  
     520  
     521  if __name__ == "__main__":
     522      if not REMOTE_NAME:
     523          print("Remote registry calls can be tested using",
     524                "'test_winreg.py --remote \\\\machine_name'")
     525      unittest.main()