Repository navigation
Conversation
…vices & Contracting Company W.L.L. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…nd Windows installer Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…ows installers Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…endencies in build.py and installer.py Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…d icon_pill warning Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…blem icons, and corporate profile Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
… high-DPI printing Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…ase notes, and README verification Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…nkco PDF Editor Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…indows 0.5.0 packaging Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…e print rendering Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…t-cli preview Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
… fix Low-IL/WinForms preview rendering Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
PreviewHandler.cs (rewritten): - Renders at the pane width x zoom (DPI-aware) via `pdfcraft-cli preview --width/--max-px`, re-renders when the pane grows, caps poster-sized pages, background render with cancellation. - Per-user (HKCU) registration on .pdf, SystemFileAssociations\.pdf, own ProgIds and the UserChoice/UserChoiceLatest ProgId; never shared browser ProgIds; backs up and restores every value; ThreadingModel=Apartment, DisableLowILProcessIsolation=1, Mark-of-the-Web removed. - Public API: RegisterPreviewHandler(path[, machineWide]), UnregisterPreviewHandler(), QueryEffectiveHandler(), IsEffectiveHandler(), Diagnose(). Records a DLL stamp and the default-app ProgId so the app can tell cheaply when to register again. pdfcraft-cli: `preview --width PX --max-px N` (+ unit and integration tests). pdfcraft (GUI): new windows_preview module checks the registration in the background via `reg query` and only runs the DLL's RegisterPreviewHandler when the DLL changed/moved or the default PDF app changed. Skipped in portable mode or with LINKCO_NO_PREVIEW_REGISTRATION=1. Installers: - Setup EXE: registers via the DLL (with fallback), unregisters HKCU+HKLM on uninstall, stops prevhost and retries file replacement/deletion. - MSI/NSIS: ThreadingModel Apartment; uninstall removes the uninstalling user's registration before the DLL is deleted. test-msi.ps1 asserts both. - build.py/installer.py: shared compile_preview_handler (/codepage:65001), rebuild when stale, register + Diagnose() report after a dev build; packaging never registers staging copies. - test-windows-integration.ps1: registration API checks, Diagnose(), valid-PDF render test. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Thumbnail provider (IThumbnailProvider, CLSID {3D8CDE4B-E969-481F-BEB0-5E3B98287416})
- New LinkcoPdfThumbnailProvider in LinkcoPdfPreviewHandler.dll (IInitializeWithStream and
IInitializeWithFile): renders page 1 through `pdfcraft-cli preview` at below-normal priority
with an 8 s timeout, fits it into the requested square and returns an opaque HBITMAP.
Password-protected or damaged PDFs keep the normal icon.
- Registered only on SystemFileAssociations\.pdf (consulted last) and Linkco's own ProgIDs, so
another PDF app's thumbnail provider keeps priority; anything it replaces is backed up and
restored on unregister. Per-user (app/build), NSIS and MSI registration, plus Setup.exe
fallback cleanup. Registration schema 3 -> 4 so existing installs re-register once.
- Diagnose() reports the effective thumbnail provider and its per-hive CodeBase.
- test-windows-integration.ps1 checks the class and interfaces and renders a real 256 px
thumbnail end to end; test-msi.ps1 checks the MSI's thumbnail rows.
packaging/windows/csharp-check
- `node packaging/windows/csharp-check/check.cjs` compiles PreviewHandler.cs and the Setup EXE as
csc.exe does (C# 5, .NET Framework 4.8 reference assemblies, /warn:4) on Linux/macOS/Windows,
using Roslyn in the .NET WebAssembly runtime (@live-codes/blazor-wasm, MIT) and
mono/reference-assemblies (MIT), downloaded into a git-ignored cache. Nothing ships.
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…ofile Linkco PDF Editor registers its preview handler and thumbnail provider per user, for each user who starts it, but the uninstallers only cleaned up the uninstalling user. Every other account was left with HKCU entries pointing Explorer at the deleted DLL: blank previews and thumbnails, even where another PDF app's handler had worked before (its backup was never restored). - PreviewHandler.cs: UnregisterPreviewHandlerForAllUsers() visits every user profile (ProfileList, S-1-5-21-* and Entra ID S-1-12-1-*): signed-in users' hives in place, the others mounted from NTUSER.DAT + UsrClass.dat (backup/restore privileges) and unmounted right after. For users with a Linkco registration it runs the existing restore-or-remove logic. HKLM is left to the installers. - RegRoot: a registry root that sends "Software\Classes\..." to a separate classes hive. The registration helpers now take it (an implicit conversion keeps the RegistryKey callers as they were), so the same code serves HKCU, HKLM and mounted profiles. - Cleanup is now right for users other than the one running it: their own UserChoice, a sweep for any of their ProgIDs still pointing at us, and restoring a backup only if its CLSID exists machine-wide or for that user. - MSI: a new deferred, non-impersonated (LocalSystem) custom action before RemoveFiles. NSIS and the machine-wide Setup EXE call it elevated. - NSIS: the uninstall command was a 1110-character -EncodedCommand. NSIS cuts strings at 1024, so it never ran. It is now a ~420-character readable -Command. - csharp-check: also runs the cleanup code taken from PreviewHandler.cs against an in-memory registry (tests/), with 35 checks: split and single hives, restoring per-user and machine-wide handlers, leaving unrelated keys and other users unchanged, no leaked handles, idempotence. - test-windows-integration.ps1 / test-msi.ps1: split-hive cleanup against the real registry (scratch HKCU keys) and the MSI custom action's deferred/no-impersonate flags. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…tall paths The app decides at start-up whether the per-user registration is current by reading it through reg.exe and comparing the recorded DLL path with its own. reg.exe prints in the console's OEM code page, which can't carry most non-ASCII text, so for a path containing e.g. an Arabic Windows user name (the per-user install lives under C:\Users\<name>\AppData\Local\Programs) the paths never matched. The app then ran PowerShell to register again, and the DLL broadcast an association change that refreshes Explorer, on every start. - PreviewHandler.cs writes PreviewHandlerDllKey: the path in ASCII (letters upper-cased; '%', control and non-ASCII UTF-16 units as %XXXX). Unregister removes it. - windows_preview.rs builds the same key from the path's exact UTF-16 (OsStrExt::encode_wide) and compares that. Older registrations, which have no key, register again once. - Shared test vectors (ASCII, Arabic, '%', Latin-1, surrogate pair) in the Rust unit tests (8 pass) and csharp-check's tests (38 checks), so the two implementations can't drift apart. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…ding Brings in the 42 upstream changes since the last merge, adapted to Linkco PDF Editor: Arabic interface (ar.tsv, right-to-left labels, Noto Sans Arabic via craft-fonts 8dcdacd), Windows single instance (files open as tabs in the running window), Per-Monitor V2 DPI manifest, signing of encrypted documents, smart-card PIN prompts, signer key-usage/EKU checks, redaction word lists and FOIA/Privacy Act code sets, bookmarks from tagged headings, ICC profiles kept, /UserUnit pages, rotated text, update-check rate-limit message, UI fixes and render performance work. Linkco adaptations: - single_instance: socket in %LOCALAPPDATA%\Linkco PDF Editor (beside Recovery), Linkco names in logs and docs; LinkcoPDFEditor.exe in the module docs. - build.rs keeps the Linkco VERSIONINFO and embeds the new DPI manifest. - main.rs: the preview-handler registration check runs only in a launch that opens a window, not in one that hands its files to the running app and exits. - updates.rs keeps the b-lincko/linkco-pdf release URL and Linkco User-Agent, plus upstream's rate-limit handling. - ar.tsv: PdfCraft -> Linkco PDF Editor, plus Arabic for the Linkco home-page strings; the Arabic bidi test follows the new name. - x509: the unknown-critical-extension message names Linkco PDF Editor. - ATTRIBUTION.toml/.md: catalog hashes recomputed, ar.tsv entry and the craft-fonts usage text (Noto Sans Arabic) taken from upstream; ATTRIBUTION.md regenerated. - build.py / installer.py fetch craft-fonts at the commit pinned in release.yml (--no-craft-fonts / LINKCO_NO_CRAFT_FONTS=1 / CRAFT_FONTS_DIR) so local builds can write Arabic and Japanese text into PDFs, and ship the fonts' OFL-*.txt licences. - README and RELEASE_NOTES describe the new features. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…co branding All 75 upstream changes, keeping the Linkco PDF Editor name, branding, Windows integration and installers. Printing: keep Linkco's Windows backend (3-tier printer detection with status, 150/300/600 dpi sheets via System.Drawing.Printing, zero margins, closest paper, landscape when wide); upstream's windows_print.ps1 backend is not adopted. Port upstream's background work onto it: printers are listed off the UI thread (PrinterSource now yields PrinterDetail with status), "Check again" also lists in the background, and jobs are rendered and spooled on a worker thread. The engine gains Session::print_max_dpi + render_imposed_sheets so rendering needs only the imposed bytes; render_print_sheets keeps its signature. PDF document icon (resource 2), recoloured to the Linkco palette, registered by the Setup EXE, NSIS and MSI (DefaultIcon ,-2). LICENSE-MIT, LICENSE-APACHE, NOTICE and LICENSE-document.txt ship beside the executables in every installer and the portable ZIP. Version 0.6.0 (preview handler assembly and installer Version strings bumped together). Polish catalog with the Linkco strings. ATTRIBUTION three-way merged (pl.tsv, minimize-2.svg, document icon entries) with hashes recomputed and ATTRIBUTION.md regenerated. README and RELEASE_NOTES updated for 0.6.0. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Whitespace-only (token-identical): long lines left by the Linkco rebrand (x509.rs, windows_preview.rs, main.rs), the 3-tier printer code in spool.rs, and the background-printing/render_imposed_sheets code from the v0.6.0 merge. Checked with rustfmt 1.88 (stable) and the repository's rustfmt.toml, which reports no changes on upstream's own files; every tracked workspace .rs file (vendor/ excluded, as in cargo fmt) now passes. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
- The dialog follows the app window (within 24 px of its edges, up to 1600x1200, never smaller than the old 820 px dialog). The preview pane takes all the room beside the settings column, which scrolls when the window is short. - Preview rasters are requested for the actual pane size (preview_rasters takes the paper box), so the bigger preview is rendered at its on-screen size. - The texture drawn for a page is the one closest to its on-screen width (pick_preview_texture). egui-wgpu makes no mipmaps, so shrinking a much larger view raster (high zoom) into the pane dropped texels and broke up lines/text. - Paper and page quads are snapped to whole physical pixels (no half-pixel blur). - Unit tests for the layout, snapping and texture choice. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…veloper credit
Print screen
- Network printers are recognised however they are connected: \\server shares, Standard
TCP/IP ports named IP_x or after the address/host (10.0.0.5, 10.0.0.5_1, host:9100), WSD,
IPP/http(s) and LPR ports, and Win32_Printer.Network (new optional 8th TSV column; the
7-column format still parses). spool::is_network_port + tests.
- Printer list marks network printers ("· Network"); statuses (Paused/Offline/Error) and the
status warning are translated; a details line shows "Network printer · Port · Driver" (full
text on hover); an empty list explains what to do (desktop builds only). kittest added.
Windows preview handler
- DiagnoseFile(path): location (local, UNC, mapped drive, OneDrive/online-only), security zone
(urlmon MapUrlToZone, with and without the Mark-of-the-Web check), whether Explorer blocks the
preview pane (Internet/Restricted zone since the Oct 2025 update), policy, and the fix.
- AllowNetworkPreview / DisallowNetworkPreview: opt-in, per server, per user Local intranet
site entry under HKCU ZoneMap (Domains\<domain>\<host>, Domains\<name>, Ranges\Linkco_<ip>);
refuses when zones are machine-wide by policy. Pure helpers tested in csharp-check (21 checks).
- Stale thumb-* temp PNGs are swept like the preview's own.
Release
- Version 1.0.0 everywhere (workspace, Cargo.lock members, preview handler assembly and the
matching NSIS/MSI registrations). RELEASE_NOTES v1.0.0, README troubleshooting.
- Help > About: "Developer: Muhammad Bilal (Linkco)" (crate::DEVELOPER), README credit.
- 10 new strings translated in all 15 maintained catalogs.
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
- Start pdfcraft-cli.exe with CreateProcess (STARTF_FORCEOFFFEEDBACK, hidden, below-normal priority) instead of System.Diagnostics.Process: no busy cursor on every selection, output captured to temp files so no wait can block on pipe EOF, and a kill-on-close job so the engine never outlives prevhost. - Pane: finished renders are parked in a slot drained by BeginInvoke and by a watchdog timer; 'still loading' notice after 8 s; the watchdog gives up 10 s after the 30 s engine timeout; timed-out/failed pages offer click-to-retry; cancelling never leaves a stale 'Loading page N...' message. - Thumbnails use the same runner. - preview.log records Initialize/DoPreview/render timings; Diagnose() adds an engine self-test, the preview host integrity level and the log tail. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…w Handler' - Guard the pane's WndProc, timers and render delivery so no exception can reach WinForms' thread-exception path and end prevhost.exe; log fatal unhandled exceptions (with stack) to preview.log. - Diagnose(): effective COM registration (HKCU over HKLM, DLL exists / version / Mark of the Web), a COM activation test like the preview host's, and recent prevhost/handler crashes from the Application event log. - packaging/windows/diagnose-preview.ps1: locates the registered DLL and prints Diagnose() (+ DiagnoseFile with -Pdf). Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…ler repair
Fixes the remaining causes of Explorer's "This file can't be previewed because
of an error in the Linkco PDF Preview Handler":
- Run in a dedicated prevhost.exe: own AppID {1C0ADB7B-F017-4384-BF73-95AA5BC5D084}
with DllSurrogate=%SystemRoot%\system32\prevhost.exe, as Microsoft requires for
managed preview handlers, instead of the shared {6d2b5079-...} host where other
vendors' handlers (e.g. PowerToys' .NET 8 handlers) and crashes take ours down.
Written by the DLL (HKCU/HKLM), installer.py fallback, NSIS and WiX; removed on
unregister/uninstall. RegistrationSchema 4 -> 5 (C# and Rust) so existing
installs re-register; the app also re-registers if the AppID key is missing.
- Every COM entry point is a guarded wrapper around a NoInlining Core method, so
JIT/type-load failures can't escape; constructors, visuals, GetWindow, SetSite,
QueryFocus, TranslateAccelerator guarded; RenderWorker can't kill the host;
SetParent failures logged.
- NSIS: stop prevhost before replacing/deleting the DLL; repair the installing
user's HKCU registration after install.
- diagnose-preview.ps1 -Repair; Diagnose() reports the host AppID/DllSurrogate,
.NET Framework release and competing .pdf preview handlers (PowerToys named).
- Tests: registry cleanup (64 checks), test-windows-integration.ps1, test-msi.ps1.
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…s runner test-preview-host.ps1 builds LinkcoPdfPreviewHandler.dll, registers it as the app and the installers do, and hosts it through prevhost.exe with PreviewHostTest.exe (CoCreateInstance LOCAL_SERVER, IInitializeWithStream, SetSite, SetWindow, visuals, DoPreview), as a normal user like Explorer, reporting each HRESULT, the surrogate's fate, what was painted, preview.log, Diagnose() and crash events. The workflow publishes the report as annotations. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…st.cs in csharp-check Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
… output Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…omparison, install in Program Files Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…ercent-decode it Uri.AbsoluteUri registered file:///C:/Program%20Files/..., and the CLR's COM activation hands CodeBase to the assembly binder without decoding it, so prevhost.exe looked for a 'Program%20Files' folder and failed with 0x80070002 (Explorer: 'an error in the Linkco PDF Preview Handler') for every install under Program Files. Write file:///C:/Program Files/... instead, re-register existing installs (schema 6, Rust check rejects escaped CodeBase), and make Diagnose()/diagnose-preview.ps1 resolve CodeBase like the CLR and test activation in a fresh native process. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…when UAC is off; test CodeBase forms machine-wide Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…Limited scheduled task, as Explorer Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…er and hosts the handler Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…se notes for the CodeBase fix Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…eport white page pixels Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…eport a hung host instead of rerunning it Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
… thumbnail of the capture Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…OleMarshalObject) so the pane paints .NET hands COM a free-threaded object by default, so Explorer's calls arrived on prevhost's RPC worker threads and DoPreview created the pane window on a thread with no message loop: every call succeeded, but the window never painted or answered a message (the pane stayed blank / kept loading). Verified with a control: Microsoft's PDF previewer in the same harness answers messages and paints. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…r registration previews end to end; release notes Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Member
|
Thank you for sharing this, @b-lincko! I'm closing it, though: it is a fork's "Linkco" rebrand rather than a change to PdfCraft. It sends update checks to the fork's repository, and it adds Python, JavaScript and C# code plus third-party brand assets, which the project can't take (Rust-only product, and AGENTS.md §1 on assets). If there is a specific feature or fix in the fork you'd like upstream, a focused PR for it on top of main would be very welcome. Please join us on Discord if you haven't already: https://discord.gg/artcraft |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.