1"""
2Manage the Windows registry
3
4-----
5Hives
6-----
7Hives are the main sections of the registry and all begin with the word HKEY.
8
9    - HKEY_LOCAL_MACHINE
10    - HKEY_CURRENT_USER
11    - HKEY_USER
12
13----
14Keys
15----
16Keys are the folders in the registry. Keys can have many nested subkeys. Keys
17can have a value assigned to them under the (Default) value name
18
19-----------------
20Values or Entries
21-----------------
22Values/Entries are name/data pairs. There can be many values in a key. The
23(Default) value corresponds to the Key itself, the rest are their own name/value
24pairs.
25
26:depends:   - PyWin32
27"""
28# When production windows installer is using Python 3, Python 2 code can be removed
29
30import logging
31import sys
32
33import salt.utils.platform
34import salt.utils.stringutils
35from salt.exceptions import CommandExecutionError
36
37try:
38    import win32gui
39    import win32api
40    import win32con
41
42    HAS_WINDOWS_MODULES = True
43except ImportError:
44    HAS_WINDOWS_MODULES = False
45
46
47PY2 = sys.version_info[0] == 2
48log = logging.getLogger(__name__)
49
50# Define the module's virtual name
51__virtualname__ = "reg"
52
53
54def __virtual__():
55    """
56    Only works on Windows systems with the PyWin32
57    """
58    if not salt.utils.platform.is_windows():
59        return (
60            False,
61            "reg execution module failed to load: "
62            "The module will only run on Windows systems",
63        )
64
65    if not HAS_WINDOWS_MODULES:
66        return (
67            False,
68            "reg execution module failed to load: "
69            "One of the following libraries did not load: "
70            "win32gui, win32con, win32api",
71        )
72
73    return __virtualname__
74
75
76def _to_mbcs(vdata):
77    """
78    Converts unicode to to current users character encoding. Use this for values
79    returned by reg functions
80    """
81    return salt.utils.stringutils.to_unicode(vdata, "mbcs")
82
83
84def _to_unicode(vdata):
85    """
86    Converts from current users character encoding to unicode. Use this for
87    parameters being pass to reg functions
88    """
89    # None does not convert to Unicode
90    if vdata is None:
91        vdata = ""
92    if isinstance(vdata, int):
93        vdata = str(vdata)
94    return salt.utils.stringutils.to_unicode(vdata, "utf-8")
95
96
97class Registry:  # pylint: disable=R0903
98    """
99    This was put in a class to delay usage until this module is actually used
100    This class contains all the lookup dicts for working with the registry
101    """
102
103    def __init__(self):
104        self.hkeys = {
105            "HKEY_CURRENT_CONFIG": win32con.HKEY_CURRENT_CONFIG,
106            "HKEY_CLASSES_ROOT": win32con.HKEY_CLASSES_ROOT,
107            "HKEY_CURRENT_USER": win32con.HKEY_CURRENT_USER,
108            "HKEY_LOCAL_MACHINE": win32con.HKEY_LOCAL_MACHINE,
109            "HKEY_USERS": win32con.HKEY_USERS,
110            "HKCC": win32con.HKEY_CURRENT_CONFIG,
111            "HKCR": win32con.HKEY_CLASSES_ROOT,
112            "HKCU": win32con.HKEY_CURRENT_USER,
113            "HKLM": win32con.HKEY_LOCAL_MACHINE,
114            "HKU": win32con.HKEY_USERS,
115        }
116        self.vtype = {
117            "REG_BINARY": win32con.REG_BINARY,
118            "REG_DWORD": win32con.REG_DWORD,
119            "REG_EXPAND_SZ": win32con.REG_EXPAND_SZ,
120            "REG_MULTI_SZ": win32con.REG_MULTI_SZ,
121            "REG_SZ": win32con.REG_SZ,
122            "REG_QWORD": win32con.REG_QWORD,
123        }
124        self.opttype = {"REG_OPTION_NON_VOLATILE": 0, "REG_OPTION_VOLATILE": 1}
125        # Return Unicode due to from __future__ import unicode_literals
126        self.vtype_reverse = {
127            win32con.REG_BINARY: "REG_BINARY",
128            win32con.REG_DWORD: "REG_DWORD",
129            win32con.REG_EXPAND_SZ: "REG_EXPAND_SZ",
130            win32con.REG_MULTI_SZ: "REG_MULTI_SZ",
131            win32con.REG_SZ: "REG_SZ",
132            win32con.REG_QWORD: "REG_QWORD",
133        }
134        self.opttype_reverse = {0: "REG_OPTION_NON_VOLATILE", 1: "REG_OPTION_VOLATILE"}
135        # delete_key_recursive uses this to check the subkey contains enough \
136        # as we do not want to remove all or most of the registry
137        self.subkey_slash_check = {
138            win32con.HKEY_CURRENT_USER: 0,
139            win32con.HKEY_LOCAL_MACHINE: 1,
140            win32con.HKEY_USERS: 1,
141            win32con.HKEY_CURRENT_CONFIG: 1,
142            win32con.HKEY_CLASSES_ROOT: 1,
143        }
144
145        self.registry_32 = {
146            True: win32con.KEY_READ | win32con.KEY_WOW64_32KEY,
147            False: win32con.KEY_READ,
148        }
149
150    def __getattr__(self, k):
151        try:
152            return self.hkeys[k]
153        except KeyError:
154            msg = "No hkey named '{0}. Try one of {1}'"
155            hkeys = ", ".join(self.hkeys)
156            raise CommandExecutionError(msg.format(k, hkeys))
157
158
159def key_exists(hive, key, use_32bit_registry=False):
160    """
161    Check that the key is found in the registry. This refers to keys and not
162    value/data pairs. To check value/data pairs, use ``value_exists``
163
164    Args:
165
166        hive (str): The hive to connect to
167
168        key (str): The key to check
169
170        use_32bit_registry (bool): Look in the 32bit portion of the registry
171
172    Returns:
173        bool: True if exists, otherwise False
174
175    Usage:
176
177        .. code-block:: python
178
179            import salt.utils.win_reg as reg
180            reg.key_exists(hive='HKLM', key='SOFTWARE\\Microsoft')
181    """
182    local_hive = _to_unicode(hive)
183    local_key = _to_unicode(key)
184
185    registry = Registry()
186    try:
187        hkey = registry.hkeys[local_hive]
188    except KeyError:
189        raise CommandExecutionError("Invalid Hive: {}".format(local_hive))
190    access_mask = registry.registry_32[use_32bit_registry]
191
192    handle = None
193    try:
194        handle = win32api.RegOpenKeyEx(hkey, local_key, 0, access_mask)
195        return True
196    except win32api.error as exc:
197        if exc.winerror == 2:
198            return False
199        raise
200    finally:
201        if handle:
202            win32api.RegCloseKey(handle)
203
204
205def value_exists(hive, key, vname, use_32bit_registry=False):
206    """
207    Check that the value/data pair is found in the registry.
208
209    .. versionadded:: 2018.3.4
210
211    Args:
212
213        hive (str): The hive to connect to
214
215        key (str): The key to check in
216
217        vname (str): The name of the value/data pair you're checking
218
219        use_32bit_registry (bool): Look in the 32bit portion of the registry
220
221    Returns:
222        bool: True if exists, otherwise False
223
224    Usage:
225
226        .. code-block:: python
227
228            import salt.utils.win_reg as reg
229            reg.value_exists(hive='HKLM',
230                                key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion',
231                                vname='CommonFilesDir')
232    """
233    local_hive = _to_unicode(hive)
234    local_key = _to_unicode(key)
235    local_vname = _to_unicode(vname)
236
237    registry = Registry()
238    try:
239        hkey = registry.hkeys[local_hive]
240    except KeyError:
241        raise CommandExecutionError("Invalid Hive: {}".format(local_hive))
242    access_mask = registry.registry_32[use_32bit_registry]
243
244    try:
245        handle = win32api.RegOpenKeyEx(hkey, local_key, 0, access_mask)
246    except win32api.error as exc:
247        if exc.winerror == 2:
248            # The key containing the value/data pair does not exist
249            return False
250        raise
251
252    try:
253        # RegQueryValueEx returns and accepts unicode data
254        _, _ = win32api.RegQueryValueEx(handle, local_vname)
255        # value/data pair exists
256        return True
257    except win32api.error as exc:
258        if exc.winerror == 2 and vname is None:
259            # value/data pair exists but is empty
260            return True
261        else:
262            # value/data pair not found
263            return False
264    finally:
265        win32api.RegCloseKey(handle)
266
267
268def broadcast_change():
269    """
270    Refresh the windows environment.
271
272    .. note::
273        This will only effect new processes and windows. Services will not see
274        the change until the system restarts.
275
276    Returns:
277        bool: True if successful, otherwise False
278
279    Usage:
280
281        .. code-block:: python
282
283            import salt.utils.win_reg
284            winreg.broadcast_change()
285    """
286    # https://msdn.microsoft.com/en-us/library/windows/desktop/ms644952(v=vs.85).aspx
287    _, res = win32gui.SendMessageTimeout(
288        win32con.HWND_BROADCAST,
289        win32con.WM_SETTINGCHANGE,
290        0,
291        0,
292        win32con.SMTO_ABORTIFHUNG,
293        5000,
294    )
295    return not bool(res)
296
297
298def list_keys(hive, key=None, use_32bit_registry=False):
299    """
300    Enumerates the subkeys in a registry key or hive.
301
302    Args:
303
304       hive (str):
305            The name of the hive. Can be one of the following:
306
307                - HKEY_LOCAL_MACHINE or HKLM
308                - HKEY_CURRENT_USER or HKCU
309                - HKEY_USERS or HKU
310                - HKEY_CLASSES_ROOT or HKCR
311                - HKEY_CURRENT_CONFIG or HKCC
312
313        key (str):
314            The key (looks like a path) to the value name. If a key is not
315            passed, the keys under the hive will be returned.
316
317        use_32bit_registry (bool):
318            Accesses the 32bit portion of the registry on 64 bit installations.
319            On 32bit machines this is ignored.
320
321    Returns:
322        list: A list of keys/subkeys under the hive or key.
323
324    Usage:
325
326        .. code-block:: python
327
328            import salt.utils.win_reg
329            winreg.list_keys(hive='HKLM', key='SOFTWARE\\Microsoft')
330    """
331
332    local_hive = _to_unicode(hive)
333    local_key = _to_unicode(key)
334
335    registry = Registry()
336    try:
337        hkey = registry.hkeys[local_hive]
338    except KeyError:
339        raise CommandExecutionError("Invalid Hive: {}".format(local_hive))
340    access_mask = registry.registry_32[use_32bit_registry]
341
342    subkeys = []
343    handle = None
344    try:
345        handle = win32api.RegOpenKeyEx(hkey, local_key, 0, access_mask)
346
347        for i in range(win32api.RegQueryInfoKey(handle)[0]):
348            subkey = win32api.RegEnumKey(handle, i)
349            if PY2:
350                subkeys.append(_to_mbcs(subkey))
351            else:
352                subkeys.append(subkey)
353
354    except win32api.error as exc:
355        if exc.winerror == 2:
356            log.debug(r"Cannot find key: %s\%s", hive, key, exc_info=True)
357            return False, r"Cannot find key: {}\{}".format(hive, key)
358        raise
359
360    finally:
361        if handle:
362            handle.Close()
363
364    return subkeys
365
366
367def list_values(hive, key=None, use_32bit_registry=False):
368    """
369    Enumerates the values in a registry key or hive.
370
371    .. note::
372        The ``(Default)`` value will only be returned if it is set, otherwise it
373        will not be returned in the list of values.
374
375    Args:
376
377        hive (str):
378            The name of the hive. Can be one of the following:
379
380                - HKEY_LOCAL_MACHINE or HKLM
381                - HKEY_CURRENT_USER or HKCU
382                - HKEY_USER or HKU
383                - HKEY_CLASSES_ROOT or HKCR
384                - HKEY_CURRENT_CONFIG or HKCC
385
386        key (str):
387            The key (looks like a path) to the value name. If a key is not
388            passed, the values under the hive will be returned.
389
390        use_32bit_registry (bool):
391            Accesses the 32bit portion of the registry on 64 bit installations.
392            On 32bit machines this is ignored.
393
394    Returns:
395        list: A list of values under the hive or key.
396
397    Usage:
398
399        .. code-block:: python
400
401            import salt.utils.win_reg
402            winreg.list_values(hive='HKLM', key='SYSTEM\\CurrentControlSet\\Services\\Tcpip')
403    """
404    local_hive = _to_unicode(hive)
405    local_key = _to_unicode(key)
406
407    registry = Registry()
408    try:
409        hkey = registry.hkeys[local_hive]
410    except KeyError:
411        raise CommandExecutionError("Invalid Hive: {}".format(local_hive))
412    access_mask = registry.registry_32[use_32bit_registry]
413    handle = None
414    values = list()
415
416    try:
417        handle = win32api.RegOpenKeyEx(hkey, local_key, 0, access_mask)
418
419        for i in range(win32api.RegQueryInfoKey(handle)[1]):
420            vname, vdata, vtype = win32api.RegEnumValue(handle, i)
421
422            if not vname:
423                vname = "(Default)"
424
425            value = {
426                "hive": local_hive,
427                "key": local_key,
428                "vname": _to_mbcs(vname),
429                "vtype": registry.vtype_reverse[vtype],
430                "success": True,
431            }
432            # Only convert text types to unicode
433            if vtype == win32con.REG_MULTI_SZ:
434                value["vdata"] = [_to_mbcs(i) for i in vdata]
435            elif vtype in [win32con.REG_SZ, win32con.REG_EXPAND_SZ]:
436                value["vdata"] = _to_mbcs(vdata)
437            else:
438                value["vdata"] = vdata
439            values.append(value)
440
441    except win32api.error as exc:
442        if exc.winerror == 2:
443            log.debug(r"Cannot find key: %s\%s", hive, key)
444            return False, r"Cannot find key: {}\{}".format(hive, key)
445        raise
446
447    finally:
448        if handle:
449            handle.Close()
450    return values
451
452
453def read_value(hive, key, vname=None, use_32bit_registry=False):
454    r"""
455    Reads a registry value entry or the default value for a key. To read the
456    default value, don't pass ``vname``
457
458    Args:
459
460        hive (str): The name of the hive. Can be one of the following:
461
462            - HKEY_LOCAL_MACHINE or HKLM
463            - HKEY_CURRENT_USER or HKCU
464            - HKEY_USER or HKU
465            - HKEY_CLASSES_ROOT or HKCR
466            - HKEY_CURRENT_CONFIG or HKCC
467
468        key (str):
469            The key (looks like a path) to the value name.
470
471        vname (str):
472            The value name. These are the individual name/data pairs under the
473            key. If not passed, the key (Default) value will be returned.
474
475        use_32bit_registry (bool):
476            Accesses the 32bit portion of the registry on 64bit installations.
477            On 32bit machines this is ignored.
478
479    Returns:
480        dict: A dictionary containing the passed settings as well as the
481            value_data if successful. If unsuccessful, sets success to False.
482
483        bool: Returns False if the key is not found
484
485        If vname is not passed:
486
487            - Returns the first unnamed value (Default) as a string.
488            - Returns none if first unnamed value is empty.
489
490    Usage:
491
492        The following will get the value of the ``version`` value name in the
493        ``HKEY_LOCAL_MACHINE\\SOFTWARE\\Salt`` key
494
495        .. code-block:: python
496
497            import salt.utils.win_reg as reg
498            reg.read_value(hive='HKLM', key='SOFTWARE\\Salt', vname='version')
499
500    Usage:
501
502        The following will get the default value of the
503        ``HKEY_LOCAL_MACHINE\\SOFTWARE\\Salt`` key
504
505        .. code-block:: python
506
507            import salt.utils.win_reg as reg
508            reg.read_value(hive='HKLM', key='SOFTWARE\\Salt')
509    """
510    # If no name is passed, the default value of the key will be returned
511    # The value name is Default
512
513    # Setup the return array
514    local_hive = _to_unicode(hive)
515    local_key = _to_unicode(key)
516    local_vname = _to_unicode(vname)
517
518    ret = {
519        "hive": local_hive,
520        "key": local_key,
521        "vname": local_vname,
522        "vdata": None,
523        "success": True,
524    }
525
526    if not vname:
527        ret["vname"] = "(Default)"
528
529    registry = Registry()
530    try:
531        hkey = registry.hkeys[local_hive]
532    except KeyError:
533        raise CommandExecutionError("Invalid Hive: {}".format(local_hive))
534    access_mask = registry.registry_32[use_32bit_registry]
535
536    try:
537        handle = win32api.RegOpenKeyEx(hkey, local_key, 0, access_mask)
538        try:
539            # RegQueryValueEx returns and accepts unicode data
540            vdata, vtype = win32api.RegQueryValueEx(handle, local_vname)
541            if vdata or vdata in [0, "", []]:
542                # Only convert text types to unicode
543                ret["vtype"] = registry.vtype_reverse[vtype]
544                if vtype == win32con.REG_MULTI_SZ:
545                    ret["vdata"] = [_to_mbcs(i) for i in vdata]
546                elif vtype in [win32con.REG_SZ, win32con.REG_EXPAND_SZ]:
547                    ret["vdata"] = _to_mbcs(vdata)
548                else:
549                    ret["vdata"] = vdata
550            else:
551                ret["comment"] = "Empty Value"
552        except win32api.error as exc:
553            if exc.winerror == 2 and vname is None:
554                ret["vdata"] = "(value not set)"
555                ret["vtype"] = "REG_SZ"
556            elif exc.winerror == 2:
557                msg = "Cannot find {} in {}\\{}".format(
558                    local_vname, local_hive, local_key
559                )
560                log.trace(exc)
561                log.trace(msg)
562                ret["comment"] = msg
563                ret["success"] = False
564            else:
565                raise
566    except win32api.error as exc:
567        if exc.winerror == 2:
568            msg = "Cannot find key: {}\\{}".format(local_hive, local_key)
569            log.trace(exc)
570            log.trace(msg)
571            ret["comment"] = msg
572            ret["success"] = False
573        else:
574            raise
575    return ret
576
577
578def set_value(
579    hive,
580    key,
581    vname=None,
582    vdata=None,
583    vtype="REG_SZ",
584    use_32bit_registry=False,
585    volatile=False,
586):
587    """
588    Sets a value in the registry. If ``vname`` is passed, it will be the value
589    for that value name, otherwise it will be the default value for the
590    specified key
591
592    Args:
593
594        hive (str):
595            The name of the hive. Can be one of the following
596
597                - HKEY_LOCAL_MACHINE or HKLM
598                - HKEY_CURRENT_USER or HKCU
599                - HKEY_USER or HKU
600                - HKEY_CLASSES_ROOT or HKCR
601                - HKEY_CURRENT_CONFIG or HKCC
602
603        key (str):
604            The key (looks like a path) to the value name.
605
606        vname (str):
607            The value name. These are the individual name/data pairs under the
608            key. If not passed, the key (Default) value will be set.
609
610        vdata (str, int, list, bytes):
611            The value you'd like to set. If a value name (vname) is passed, this
612            will be the data for that value name. If not, this will be the
613            (Default) value for the key.
614
615            The type of data this parameter expects is determined by the value
616            type specified in ``vtype``. The correspondence is as follows:
617
618                - REG_BINARY: Binary data (str in Py2, bytes in Py3)
619                - REG_DWORD: int
620                - REG_EXPAND_SZ: str
621                - REG_MULTI_SZ: list of str
622                - REG_QWORD: int
623                - REG_SZ: str
624
625                .. note::
626                    When setting REG_BINARY, string data will be converted to
627                    binary. You can pass base64 encoded using the ``binascii``
628                    built-in module. Use ``binascii.b2a_base64('your data')``
629
630            .. note::
631                The type for the (Default) value is always REG_SZ and cannot be
632                changed.
633
634            .. note::
635                This parameter is optional. If not passed, the Key will be
636                created with no associated item/value pairs.
637
638        vtype (str):
639            The value type. The possible values of the vtype parameter are
640            indicated above in the description of the vdata parameter.
641
642        use_32bit_registry (bool):
643            Sets the 32bit portion of the registry on 64bit installations. On
644            32bit machines this is ignored.
645
646        volatile (bool):
647            When this parameter has a value of True, the registry key will be
648            made volatile (i.e. it will not persist beyond a system reset or
649            shutdown). This parameter only has an effect when a key is being
650            created and at no other time.
651
652    Returns:
653        bool: True if successful, otherwise False
654
655    Usage:
656
657        This will set the version value to 2015.5.2 in the SOFTWARE\\Salt key in
658        the HKEY_LOCAL_MACHINE hive
659
660        .. code-block:: python
661
662            import salt.utils.win_reg
663            winreg.set_value(hive='HKLM', key='SOFTWARE\\Salt', vname='version', vdata='2015.5.2')
664
665    Usage:
666
667        This function is strict about the type of vdata. For instance this
668        example will fail because vtype has a value of REG_SZ and vdata has a
669        type of int (as opposed to str as expected).
670
671        .. code-block:: python
672
673            import salt.utils.win_reg
674            winreg.set_value(hive='HKLM', key='SOFTWARE\\Salt', vname='str_data', vdata=1.2)
675
676    Usage:
677
678        In this next example vdata is properly quoted and should succeed.
679
680        .. code-block:: python
681
682            import salt.utils.win_reg
683            winreg.set_value(hive='HKLM', key='SOFTWARE\\Salt', vname='str_data', vdata='1.2')
684
685    Usage:
686
687        This is an example of using vtype REG_BINARY. Both ``set_value``
688        commands will set the same value ``Salty Test``
689
690        .. code-block:: python
691
692            import salt.utils.win_reg
693            winreg.set_value(hive='HKLM', key='SOFTWARE\\Salt', vname='bin_data', vdata='Salty Test', vtype='REG_BINARY')
694
695            import binascii
696            bin_data = binascii.b2a_base64('Salty Test')
697            winreg.set_value(hive='HKLM', key='SOFTWARE\\Salt', vname='bin_data_encoded', vdata=bin_data, vtype='REG_BINARY')
698
699    Usage:
700
701        An example using vtype REG_MULTI_SZ is as follows:
702
703        .. code-block:: python
704
705            import salt.utils.win_reg
706            winreg.set_value(hive='HKLM', key='SOFTWARE\\Salt', vname='list_data', vdata=['Salt', 'is', 'great'], vtype='REG_MULTI_SZ')
707    """
708    local_hive = _to_unicode(hive)
709    local_key = _to_unicode(key)
710    local_vname = _to_unicode(vname)
711    local_vtype = _to_unicode(vtype)
712
713    registry = Registry()
714    try:
715        hkey = registry.hkeys[local_hive]
716    except KeyError:
717        raise CommandExecutionError("Invalid Hive: {}".format(local_hive))
718    vtype_value = registry.vtype[local_vtype]
719    access_mask = registry.registry_32[use_32bit_registry] | win32con.KEY_ALL_ACCESS
720
721    local_vdata = cast_vdata(vdata=vdata, vtype=local_vtype)
722
723    if volatile:
724        create_options = registry.opttype["REG_OPTION_VOLATILE"]
725    else:
726        create_options = registry.opttype["REG_OPTION_NON_VOLATILE"]
727
728    handle = None
729    try:
730        handle, result = win32api.RegCreateKeyEx(
731            hkey, local_key, access_mask, Options=create_options
732        )
733        msg = (
734            "Created new key: %s\\%s" if result == 1 else "Opened existing key: %s\\%s"
735        )
736        log.debug(msg, local_hive, local_key)
737
738        try:
739            win32api.RegSetValueEx(handle, local_vname, 0, vtype_value, local_vdata)
740            win32api.RegFlushKey(handle)
741            broadcast_change()
742            return True
743        except TypeError as exc:
744            log.exception('"vdata" does not match the expected data type.\n%s', exc)
745            return False
746        except (SystemError, ValueError) as exc:
747            log.exception("Encountered error setting registry value.\n%s", exc)
748            return False
749
750    except win32api.error as exc:
751        log.exception(
752            "Error creating/opening key: %s\\%s\n%s",
753            local_hive,
754            local_key,
755            exc.winerror,
756        )
757        return False
758
759    finally:
760        if handle:
761            win32api.RegCloseKey(handle)
762
763
764def cast_vdata(vdata=None, vtype="REG_SZ"):
765    """
766    Cast the ``vdata` value to the appropriate data type for the registry type
767    specified in ``vtype``
768
769    Args:
770
771        vdata (str, int, list, bytes): The data to cast
772
773        vtype (str):
774            The type of data to be written to the registry. Must be one of the
775            following:
776
777                - REG_BINARY
778                - REG_DWORD
779                - REG_EXPAND_SZ
780                - REG_MULTI_SZ
781                - REG_QWORD
782                - REG_SZ
783
784    Returns:
785        The vdata cast to the appropriate type. Will be unicode string, binary,
786        list of unicode strings, or int
787
788    Usage:
789
790        .. code-block:: python
791
792            import salt.utils.win_reg
793            winreg.cast_vdata(vdata='This is the string', vtype='REG_SZ')
794    """
795    # Check data type and cast to expected type
796    # int will automatically become long on 64bit numbers
797    # https://www.python.org/dev/peps/pep-0237/
798
799    registry = Registry()
800    vtype_value = registry.vtype[vtype]
801
802    # String Types to Unicode
803    if vtype_value in [win32con.REG_SZ, win32con.REG_EXPAND_SZ]:
804        return _to_unicode(vdata)
805    # Don't touch binary... if it's binary
806    elif vtype_value == win32con.REG_BINARY:
807        if isinstance(vdata, str):
808            # Unicode data must be encoded
809            return vdata.encode("utf-8")
810        return vdata
811    # Make sure REG_MULTI_SZ is a list of strings
812    elif vtype_value == win32con.REG_MULTI_SZ:
813        return [_to_unicode(i) for i in vdata]
814    # Make sure REG_QWORD is a 64 bit integer
815    elif vtype_value == win32con.REG_QWORD:
816        return int(vdata)
817    # Everything else is int
818    else:
819        return int(vdata)
820
821
822def delete_key_recursive(hive, key, use_32bit_registry=False):
823    """
824    .. versionadded:: 2015.5.4
825
826    Delete a registry key to include all subkeys and value/data pairs.
827
828    Args:
829
830        hive (str):
831            The name of the hive. Can be one of the following
832
833                - HKEY_LOCAL_MACHINE or HKLM
834                - HKEY_CURRENT_USER or HKCU
835                - HKEY_USER or HKU
836                - HKEY_CLASSES_ROOT or HKCR
837                - HKEY_CURRENT_CONFIG or HKCC
838
839            key (str):
840                The key to remove (looks like a path)
841
842            use_32bit_registry (bool):
843                Deletes the 32bit portion of the registry on 64bit
844                installations. On 32bit machines this is ignored.
845
846    Returns:
847        dict: A dictionary listing the keys that deleted successfully as well as
848            those that failed to delete.
849
850    Usage:
851
852        The following example will remove ``salt`` and all its subkeys from the
853        ``SOFTWARE`` key in ``HKEY_LOCAL_MACHINE``:
854
855        .. code-block:: python
856
857            import salt.utils.win_reg
858            winreg.delete_key_recursive(hive='HKLM', key='SOFTWARE\\DeleteMe')
859    """
860
861    local_hive = _to_unicode(hive)
862    local_key = _to_unicode(key)
863
864    # Instantiate the registry object
865    registry = Registry()
866    try:
867        hkey = registry.hkeys[local_hive]
868    except KeyError:
869        raise CommandExecutionError("Invalid Hive: {}".format(local_hive))
870    key_path = local_key
871    access_mask = registry.registry_32[use_32bit_registry] | win32con.KEY_ALL_ACCESS
872
873    if not key_exists(local_hive, local_key, use_32bit_registry):
874        log.debug('"%s\\%s" not found', hive, key)
875        return False
876
877    if (len(key) > 1) and (key.count("\\", 1) < registry.subkey_slash_check[hkey]):
878        log.error('"%s\\%s" is too close to root, not safe to remove', hive, key)
879        return False
880
881    # Functions for traversing the registry tree
882    def _subkeys(_key):
883        """
884        Enumerate keys
885        """
886        i = 0
887        while True:
888            try:
889                subkey = win32api.RegEnumKey(_key, i)
890                yield _to_mbcs(subkey)
891                i += 1
892            except win32api.error:
893                break
894
895    def _traverse_registry_tree(_hkey, _keypath, _ret, _access_mask):
896        """
897        Traverse the registry tree i.e. dive into the tree
898        """
899        _key = win32api.RegOpenKeyEx(_hkey, _keypath, 0, _access_mask)
900        for subkeyname in _subkeys(_key):
901            subkeypath = "{}\\{}".format(_keypath, subkeyname)
902            _ret = _traverse_registry_tree(_hkey, subkeypath, _ret, access_mask)
903            _ret.append(subkeypath)
904        return _ret
905
906    # Get a reverse list of registry keys to be deleted
907    key_list = []
908    key_list = _traverse_registry_tree(hkey, key_path, key_list, access_mask)
909    # Add the top level key last, all subkeys must be deleted first
910    key_list.append(key_path)
911
912    ret = {"Deleted": [], "Failed": []}
913
914    # Delete all sub_keys
915    for sub_key_path in key_list:
916        key_handle = None
917        try:
918            key_handle = win32api.RegOpenKeyEx(hkey, sub_key_path, 0, access_mask)
919            try:
920                win32api.RegDeleteKey(key_handle, "")
921                ret["Deleted"].append(r"{}\{}".format(hive, sub_key_path))
922            except OSError as exc:
923                log.error(exc, exc_info=True)
924                ret["Failed"].append(r"{}\{} {}".format(hive, sub_key_path, exc))
925        except win32api.error as exc:
926            log.error(exc, exc_info=True)
927            ret["Failed"].append(r"{}\{} {}".format(hive, sub_key_path, exc.strerror))
928        finally:
929            if key_handle:
930                win32api.CloseHandle(key_handle)
931
932    broadcast_change()
933
934    return ret
935
936
937def delete_value(hive, key, vname=None, use_32bit_registry=False):
938    """
939    Delete a registry value entry or the default value for a key.
940
941    Args:
942
943        hive (str):
944            The name of the hive. Can be one of the following
945
946                - HKEY_LOCAL_MACHINE or HKLM
947                - HKEY_CURRENT_USER or HKCU
948                - HKEY_USER or HKU
949                - HKEY_CLASSES_ROOT or HKCR
950                - HKEY_CURRENT_CONFIG or HKCC
951
952        key (str):
953            The key (looks like a path) to the value name.
954
955        vname (str):
956            The value name. These are the individual name/data pairs under the
957            key. If not passed, the key (Default) value will be deleted.
958
959        use_32bit_registry (bool):
960            Deletes the 32bit portion of the registry on 64bit installations. On
961            32bit machines this is ignored.
962
963    Return:
964        bool: True if successful, otherwise False
965
966    Usage:
967
968        .. code-block:: python
969
970            import salt.utils.win_reg
971            winreg.delete_value(hive='HKLM', key='SOFTWARE\\SaltTest', vname='version')
972    """
973    local_hive = _to_unicode(hive)
974    local_key = _to_unicode(key)
975    local_vname = _to_unicode(vname)
976
977    registry = Registry()
978    try:
979        hkey = registry.hkeys[local_hive]
980    except KeyError:
981        raise CommandExecutionError("Invalid Hive: {}".format(local_hive))
982    access_mask = registry.registry_32[use_32bit_registry] | win32con.KEY_ALL_ACCESS
983
984    handle = None
985    try:
986        handle = win32api.RegOpenKeyEx(hkey, local_key, 0, access_mask)
987        win32api.RegDeleteValue(handle, local_vname)
988        broadcast_change()
989        return True
990    except win32api.error as exc:
991        if exc.winerror == 2:
992            return None
993        raise
994    finally:
995        if handle:
996            win32api.RegCloseKey(handle)
997