master
John Lauer 0.9.274: Wiki #71 root cause: on a OneDrive-redirected Documents the bridge used %USERPROFILE%/Documents while KiCad re… d9e363d 2mo ago
"""Windows shell folders, resolved the way KiCad resolves them.

WHY (wiki #71, Ray, 2026-09-03; and the PCM bug the day before). KiCad finds the
user's KiCad folder through the SHELL Documents known folder
(wxStandardPaths::GetDocumentsDir -> FOLDERID_Documents). With OneDrive Known
Folder Redirection that is %USERPROFILE%\\OneDrive\\Documents, NOT
%USERPROFILE%\\Documents. This bridge used the naive path, so on a redirected
box it created and wrote a SECOND, empty Adom library that KiCad never reads,
while KiCad's real one sat under OneDrive with every symbol in it. Every
"installed but invisible" report on such a box traces back to this.
"""

from __future__ import annotations

import os
from pathlib import Path


def shell_documents_dir() -> Path | None:
    """FOLDERID_Documents via SHGetKnownFolderPath, or None off-Windows."""
    try:
        import ctypes
        from ctypes import wintypes

        class GUID(ctypes.Structure):
            _fields_ = [("Data1", wintypes.DWORD), ("Data2", wintypes.WORD),
                        ("Data3", wintypes.WORD), ("Data4", wintypes.BYTE * 8)]
        guid = GUID(0xFDD39AD0, 0x238F, 0x46AF,
                    (wintypes.BYTE * 8)(0xAD, 0xB4, 0x6C, 0x85, 0x48, 0x03, 0x69, 0xC7))
        out = ctypes.c_wchar_p()
        if ctypes.windll.shell32.SHGetKnownFolderPath(ctypes.byref(guid), 0, None, ctypes.byref(out)) == 0:
            p = Path(out.value)
            ctypes.windll.ole32.CoTaskMemFree(out)
            return p
    except Exception:  # pylint: disable=broad-except
        pass
    return None


def documents_candidates() -> list[Path]:
    """Shell Documents FIRST (what KiCad uses), naive %USERPROFILE%\\Documents
    second (what this bridge used to assume). Both, de-duplicated, in that order,
    so a caller can prefer KiCad's answer and still find a legacy tree."""
    out: list[Path] = []
    s = shell_documents_dir()
    if s:
        out.append(s)
    up = os.environ.get("USERPROFILE")
    if up:
        n = Path(up) / "Documents"
        if not out or n.resolve() != out[0].resolve():
            out.append(n)
    return out