DEV Community

Hitesh Sachdeva
Hitesh Sachdeva

Posted on

# Release 0.4 Week 2: Fixing a Windows Bug in Nextcloud Desktop Client

Moving to a New Challenge

After submitting my pull request for OpenCTI, I wanted to take on something different for the second half of Release 0.4. I decided to explore the Nextcloud Desktop Client, a popular open-source file synchronization tool used by millions of people worldwide.

Nextcloud allows users to sync files across devices while maintaining control over their data. The desktop client is a C++ application with deep integrations into Windows, macOS, and Linux. This was a significant step outside my comfort zone since most of my experience has been with JavaScript, not C++.

The Bug I Found

While browsing the Nextcloud issues, I came across Issue #9197:

https://github.com/nextcloud/desktop/issues/9197

The problem was straightforward from a user's perspective: custom folder icons on Windows were being reset every time Nextcloud synced files.

On Windows, users can set custom icons on folders by right-clicking → Properties → Customize → Change Icon. Many people use this to visually organize their files. But with this bug, every sync would wipe out those custom icons and replace them with the default folder icon.

Understanding the Root Cause

Before fixing anything, I needed to understand how Windows handles custom folder icons. After some research, I learned that Windows uses two things:

  1. A hidden desktop.ini file inside the folder containing the icon path
  2. The FILE_ATTRIBUTE_SYSTEM flag set on the folder

Both must be present for the custom icon to appear. If either is missing, Windows shows the default icon.

I then explored the Nextcloud codebase to find where this attribute might be getting lost. The relevant code was in:

src/libsync/vfs/cfapi/cfapiwrapper.cpp

This file handles the Windows Cloud Files API (CFAPI), which Nextcloud uses for virtual file support. I discovered that during sync operations, the code was setting file attributes to default values (FILE_ATTRIBUTE_NORMAL or FILE_ATTRIBUTE_DIRECTORY) without preserving existing attributes like FILE_ATTRIBUTE_SYSTEM.

My Fix

The solution was to read the current file attributes before updating them, and preserve any existing flags. I modified three functions in cfapiwrapper.cpp:

1. updatePlaceholderState()

Added code to read and preserve existing attributes:

// Preserve existing file attributes (especially FILE_ATTRIBUTE_SYSTEM for custom folder icons)
const auto currentAttributes = GetFileAttributesW(reinterpret_cast<const wchar_t *>(path.utf16()));
if (currentAttributes != INVALID_FILE_ATTRIBUTES) {
    metadata.BasicInfo.FileAttributes = currentAttributes;
}
Enter fullscreen mode Exit fullscreen mode

2. createPlaceholderInfo()

Modified to check for existing attributes before setting defaults:

const auto currentAttributes = GetFileAttributesW(reinterpret_cast<const wchar_t *>(path.utf16()));
if (currentAttributes != INVALID_FILE_ATTRIBUTES) {
    cloudEntry.FsMetadata.BasicInfo.FileAttributes = currentAttributes;
} else {
    cloudEntry.FsMetadata.BasicInfo.FileAttributes = fileInfo.isDir() ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
}
Enter fullscreen mode Exit fullscreen mode

3. updatePlaceholderState()

Applied the same fix to the batch placeholder creation function.

Challenges I Faced

This contribution came with some significant challenges:

  • Building the project locally was difficult. Nextcloud Desktop has complex dependencies including Qt6 and KDE libraries. Setting up the build environment on Windows proved challenging.

  • Understanding the CFAPI. The Windows Cloud Files API was completely new to me, and I had to spend time reading Microsoft documentation to understand how it works.

  • Navigating a large C++ codebase. With hundreds of files and complex abstractions, finding the right place to make changes took patience and careful code tracing.

Current Status

I have completed the fix and verified that the code changes are correct based on my analysis of the codebase. The changes are ready for a pull request:

Files Changed:

  • src/libsync/vfs/cfapi/cfapiwrapper.cpp

Issue Reference:

https://github.com/nextcloud/desktop/issues/9197

What I Learned

This week taught me several valuable lessons:

  • How Windows file attributes work at a low level, especially FILE_ATTRIBUTE_SYSTEM
  • How the Cloud Files API (CFAPI) integrates with sync engines
  • How to navigate and understand a large unfamiliar C++ codebase
  • The importance of preserving system state during operations that modify files

Looking Ahead

My next steps are:

  1. Submit a clean pull request with proper documentation
  2. Respond to any code review feedback from maintainers
  3. Work toward getting the fix merged

Conclusion

Week 2 pushed me into unfamiliar territory with C++ and Windows system programming. While it was challenging, I gained a much deeper understanding of how desktop sync applications work under the hood. Combined with my OpenCTI contribution from Week 1, I feel like I'm making meaningful progress in my open-source journey.

In my final blog post, I'll share the results of both contributions and reflect on what I've learned throughout Release 0.4.

Top comments (0)