Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions apps/shelldrive-host/service.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ static struct svc_state {
const svc_scm_ops *scm_ops; /* svc_opts seams of service.status and service.repair_data */
const svc_repair_ops *repair_ops;
const svc_sysproxy_ops *sysproxy; /* proxy = system seams (svc_opts.sysproxy_ops); the shipping ops refuse by policy */
DWORD (WINAPI *logical_drives)(void); /* svc_opts.logical_drives; GetLogicalDrives when the opts give none */
const wchar_t *repair_base;
int running, stopping;
int test_all_admin; /* SD_SVC_TEST_HOOKS only, see caller_is_admin */
Expand Down Expand Up @@ -685,7 +686,7 @@ static int letter_taken_locked(wchar_t l)
/* The drive letter an auto mount takes: the highest free letter from Z: down to D: (0 when none). */
static wchar_t pick_letter_locked(void)
{
DWORD used = GetLogicalDrives();
DWORD used = g.logical_drives();
wchar_t l;
for (l = L'Z'; l >= L'D'; l--) {
DWORD bit = 1ul << (l - L'A');
Expand Down Expand Up @@ -2613,7 +2614,7 @@ static sd_err svc_mount_queue(const char *key, const char *tgt, char out_id[16],
}
if (letter == 0)
letter = pick_letter_locked();
if (letter == 0 || letter_taken_locked(letter) || (GetLogicalDrives() & (1ul << (letter - L'A')))) {
if (letter == 0 || letter_taken_locked(letter) || (g.logical_drives() &(1ul << (letter - L'A')))) {
sd_mutex_unlock(&g.lock);
sd_free(copy);
*code = "target_in_use";
Expand Down Expand Up @@ -3424,6 +3425,7 @@ int svc_run(const svc_opts *o)
g.repair_ops = o ? o->repair_ops : NULL;
g.repair_base = o ? o->repair_base : NULL;
g.sysproxy = (o && o->sysproxy_ops) ? o->sysproxy_ops : &k_sysproxy_shipping;
g.logical_drives = (o && o->logical_drives) ? o->logical_drives : GetLogicalDrives;
#ifdef SD_SVC_TEST_HOOKS
g.test_all_admin = o ? o->test_all_admin : 0;
g.dacl_extra = o ? o->dacl_extra_ace : NULL;
Expand Down
4 changes: 4 additions & 0 deletions apps/shelldrive-host/service.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ typedef struct svc_opts {
const wchar_t *repair_base;
/* proxy = system seams of service profiles (svc_sysproxy_ops above). NULL = refused (allow 0) with the real read. */
const svc_sysproxy_ops *sysproxy_ops;
/* The drive letters in use on the machine (GetLogicalDrives bits), read when a mount picks or checks its letter.
NULL = GetLogicalDrives. Tests with the fake backend pass a fixed mask, so the letter of an auto mount does not
depend on drives other processes mount meanwhile. */
DWORD (WINAPI *logical_drives)(void);
} svc_opts;

/* Blocks until svc_request_stop (or a stop control). Returns 0, or 1 when the core cannot start (no pipe, no folder
Expand Down
13 changes: 12 additions & 1 deletion tests/unit/sd_svc/test_service.c
Original file line number Diff line number Diff line change
Expand Up @@ -2080,6 +2080,13 @@ static HANDLE g_boot_running;
static HANDLE g_boot_thread;
static int g_boot_rc = -1;

/* The drives the boot cores see in use: only C:. The fake backend maps no letter, so with this fixed mask the letter
of an auto mount depends only on the service's own records, not on drives other tests mount meanwhile. */
static DWORD WINAPI boot_logical_drives(void)
{
return 1ul << (L'C' - L'A');
}

static void boot_core_running(void *ctx)
{
SetEvent((HANDLE)ctx);
Expand All @@ -2103,6 +2110,7 @@ static int start_boot_core(svc_opts *o, const wchar_t *root)
o->test_all_admin = 1;
o->dacl_extra_ace = L"(A;OICI;FA;;;OW)";
o->on_running = boot_core_running;
o->logical_drives = boot_logical_drives;
if (sd_ipc_current_identity(sid, SD_COUNTOF(sid), NULL) != SD_OK)
return 0;
_snwprintf_s(suffix, SD_COUNTOF(suffix), _TRUNCATE, L"svc%lu", (unsigned long)GetCurrentProcessId());
Expand Down Expand Up @@ -2337,7 +2345,10 @@ SD_TEST(svc_autostart_failed_mount_is_replaced_by_a_new_mount)
sd_json_free(res);
}
SD_CHECK(mid2[0] != 0 && strcmp(mid2, mid) != 0); /* a new mount id */
SD_CHECK_STR(tgt2, tgt1); /* the same letter comes back */
/* the same letter comes back: the boot core sees only C: in use (boot_logical_drives), so the autostart took Z:,
and the new mount takes Z: again only if the failed record no longer holds it (it would get Y: otherwise) */
SD_CHECK_STR(tgt1, "Z:");
SD_CHECK_STR(tgt2, tgt1);
SD_CHECK(wait_state(c, mid, "gone", 10000, NULL)); /* the failed record was released */
SD_CHECK(wait_state(c, mid2, "mounted", 20000, NULL)); /* the drive is up without an unmount */
/* a live mount of the profile is still refused */
Expand Down