/* Attempt to impersonate a client and open a file for the filedisk. */ static NTSTATUS STDCALL WvFilediskOpen_( IN WV_SP_FILEDISK_T filedisk, IN PANSI_STRING file_path ) { WV_S_FILEDISK_OPENER_ opener; /* Allocate and convert the file path from ANSI to Unicode. */ opener.status = RtlAnsiStringToUnicodeString( opener.file_path, file_path, TRUE ); if (!NT_SUCCESS(opener.status)) { DBG("Couldn't allocate Unicode file path!\n"); goto err_ansi_to_unicode; } /* Build the impersonation context. */ opener.status = WvFilediskCreateClientSecurity(&filedisk->impersonation); if (!NT_SUCCESS(opener.status)) { DBG("Couldn't build impersonation context!\n"); goto err_impersonation; } /* Build the rest of the work item. */ opener.item->Func = WvFilediskOpenInThread_; opener.filedisk = filedisk; KeInitializeEvent(opener.completion, SynchronizationEvent, FALSE); /* Attempt to open the file from within the filedisk's thread. */ if (!(WvlThreadAddItem(filedisk->Thread, opener.item))) { DBG("Filedisk thread not active!\n"); goto err_add_item; } KeWaitForSingleObject( opener.completion, Executive, KernelMode, FALSE, NULL ); /* Fall through to free resources and return status. */ err_add_item: err_impersonation: RtlFreeUnicodeString(opener.file_path); err_ansi_to_unicode: return opener.status; }
/* The thread responsible for hot-swapping filedisks. */ static VOID STDCALL WvFilediskHotSwapThread_(IN OUT WVL_SP_THREAD_ITEM item) { LARGE_INTEGER timeout; WVL_SP_THREAD thread = CONTAINING_RECORD(item, WVL_S_THREAD, Main); WVL_SP_THREAD_ITEM work_item; WV_SP_FILEDISK_HOT_SWAPPER_ info; /* Wake up at least every 10 seconds. */ timeout.QuadPart = -100000000LL; while ( (thread->State == WvlThreadStateStarted) || (thread->State == WvlThreadStateStopping) ) { /* Wait for the work signal or the timeout. */ KeWaitForSingleObject( &thread->Signal, Executive, KernelMode, FALSE, &timeout ); work_item = WvlThreadGetItem(thread); if (!work_item) continue; if (work_item->Func != WvFilediskHotSwapThread_) { DBG("Unknown work item.\n"); continue; } info = CONTAINING_RECORD( work_item, WV_S_FILEDISK_HOT_SWAPPER_, item[0] ); /* Attempt a hot swap. */ if (WvFilediskHotSwap_(info->filedisk, info->filename)) { /* Success. */ RtlFreeUnicodeString(info->filename); wv_free(info); } else { /* Re-enqueue. */ WvlThreadAddItem(thread, info->item); } /* Reset the work signal. */ KeResetEvent(&thread->Signal); } /* while thread is running. */ return; }
/** * Initiate a filedisk hot-swap to another file. * * @v filedisk The filedisk to be hot-swapped. * @v file The ANSI filename for swapping to. */ VOID STDCALL WvFilediskHotSwap(IN WV_SP_FILEDISK_T filedisk, IN PCHAR file) { static WVL_S_THREAD thread = { /* Main */ { /* Link */ {0}, /* Func */ WvFilediskHotSwapThread_, }, /* State */ WvlThreadStateNotStarted, }; WV_SP_FILEDISK_HOT_SWAPPER_ hot_swapper; ANSI_STRING file_ansi; NTSTATUS status; hot_swapper = wv_malloc(sizeof *hot_swapper); if (!hot_swapper) { DBG("Non-critical: Couldn't allocate work item.\n"); return; } /* Build the Unicode string. */ RtlInitAnsiString(&file_ansi, file); hot_swapper->filename->Buffer = NULL; status = RtlAnsiStringToUnicodeString( hot_swapper->filename, &file_ansi, TRUE ); if (!NT_SUCCESS(status)) { DBG("Non-critical: Couldn't allocate unicode string.\n"); wv_free(hot_swapper); return; } /* Build the rest of the work item. */ hot_swapper->item->Func = WvFilediskHotSwapThread_; hot_swapper->filedisk = filedisk; /* Start the thread. If it's already been started, no matter. */ WvlThreadStart(&thread); /* Add the hot-swapper work item. */ if (!WvlThreadAddItem(&thread, hot_swapper->item)) { DBG("Non-critical: Couldn't add work item.\n"); RtlFreeUnicodeString(hot_swapper->filename); wv_free(hot_swapper); } /* The thread is responsible for freeing the work item and file path. */ return; }
/** * Initiate a search for a GRUB4DOS backing disk. * * @v filedisk The filedisk whose backing disk we need. */ static BOOLEAN STDCALL WvFilediskG4dFindBackingDisk( IN WV_SP_FILEDISK_T filedisk ) { SP_WV_FILEDISK_G4D_FIND_BACKING_DISK finder; KIRQL irql; finder = wv_malloc(sizeof *finder); if (!finder) { DBG("Couldn't allocate work item!\n"); goto err_finder; } KeAcquireSpinLock(&WvFindDiskLock, &irql); ++WvFindDisk; KeReleaseSpinLock(&WvFindDiskLock, irql); finder->item->Func = WvFilediskG4dFindBackingDisk_; finder->filedisk = filedisk; /* Add the hot-swapper work item. */ if (!WvlThreadAddItem(filedisk->Thread, finder->item)) { DBG("Couldn't add work item!\n"); goto err_work_item; } /* The thread is responsible for freeing the work item. */ return TRUE; err_work_item: KeAcquireSpinLock(&WvFindDiskLock, &irql); --WvFindDisk; KeReleaseSpinLock(&WvFindDiskLock, irql); wv_free(finder); err_finder: return FALSE; }