| 56 | } |
| 57 | |
| 58 | NTSTATUS Load( |
| 59 | PVOID hModule, |
| 60 | LPCWSTR ModuleName, |
| 61 | OPTIONAL LoadableModules::_OnLoad OnLoad = NULL, |
| 62 | OPTIONAL LoadableModules::_OnUnload OnUnload = NULL, |
| 63 | OPTIONAL LoadableModules::_OnDeviceControl OnDeviceControl = NULL |
| 64 | ) { |
| 65 | if (!hModule || !ModuleName) return STATUS_INVALID_PARAMETER; |
| 66 | |
| 67 | WideString Name(ModuleName); |
| 68 | Name.Trim().ToLowerCase(); |
| 69 | if (!Name.GetLength()) return STATUS_INVALID_PARAMETER; |
| 70 | |
| 71 | BOOLEAN AlreadyLoaded = FALSE; |
| 72 | Lock.Lock(); |
| 73 | for (auto& Module : Modules) { |
| 74 | AlreadyLoaded = Module.hModule == hModule || Module.ModuleName == Name; |
| 75 | if (AlreadyLoaded) break; |
| 76 | } |
| 77 | Lock.Unlock(); |
| 78 | |
| 79 | if (AlreadyLoaded) |
| 80 | return STATUS_ALREADY_COMPLETE; |
| 81 | |
| 82 | NTSTATUS Status = OnLoad ? OnLoad(hModule, ModuleName) : STATUS_SUCCESS; |
| 83 | |
| 84 | if (Status == STATUS_SUCCESS) { |
| 85 | Lock.Lock(); |
| 86 | MODULE_INFO Module = {}; |
| 87 | Module.ModuleName = Name; |
| 88 | Module.hModule = hModule; |
| 89 | Module.OnUnload = OnUnload; |
| 90 | Module.OnDeviceControl = OnDeviceControl; |
| 91 | Module.CompletionEvent = new KEVENT; |
| 92 | KeInitializeEvent(Module.CompletionEvent, NotificationEvent, TRUE); |
| 93 | Modules.InsertTail(Module); |
| 94 | Lock.Unlock(); |
| 95 | } |
| 96 | |
| 97 | return Status; |
| 98 | } |
| 99 | |
| 100 | NTSTATUS Call(PVOID hModule, ULONG CtlCode, OPTIONAL PVOID Argument = NULL) { |
| 101 | if (!hModule) return STATUS_INVALID_PARAMETER; |
no test coverage detected