+HINSTANCE ClientLoadLibrary(PUNICODE_STRING pstrLibName,
+ PUNICODE_STRING pstrInitFunc,
+ BOOL Unload,
+ BOOL ApiHook)
+{
+ HINSTANCE hLibrary;
+ PVOID pInitFunction;
+ NTSTATUS Status;
+ ANSI_STRING InitFuncName;
+ BOOL Result = FALSE;
+
+ /* Check if we have to load the module */
+ if(Unload == FALSE)
+ {
+ ASSERT(pstrLibName->Buffer != NULL);
+
+ /* Load it */
+ hLibrary = LoadLibrary(pstrLibName->Buffer);
+ if(hLibrary == 0)
+ {
+ return hLibrary;
+ }
+
+ if(ApiHook == FALSE)
+ {
+ /* There is nothing more to do for a global hook*/
+ return hLibrary;
+ }
+
+ /* Initialize the user api hook */
+ ASSERT(pstrInitFunc->Buffer);
+
+ Status = RtlUnicodeStringToAnsiString(&InitFuncName,
+ pstrInitFunc,
+ TRUE);
+
+ /* Get the address of the initialization routine */
+ pInitFunction = GetProcAddress(hLibrary, InitFuncName.Buffer);
+ if(pInitFunction)
+ {
+ /* Call the initialization routine */
+ Result = InitUserApiHook(hLibrary, (USERAPIHOOKPROC)pInitFunction);
+ }
+ RtlFreeAnsiString(&InitFuncName);
+
+ /* In case of error unload the library */
+ if(Result == FALSE)
+ {
+ FreeLibrary(hLibrary);
+ hLibrary = 0;
+ }
+ }
+ else
+ {
+ /* Cleanup user api hook before unloading */
+ if(ApiHook == TRUE)
+ {
+ Result = ClearUserApiHook(ghmodUserApiHook);
+ hLibrary = Result ? ghmodUserApiHook : 0;
+ }
+ else
+ {
+ hLibrary = GetModuleHandle(pstrLibName->Buffer);
+ Result = (hLibrary != 0);
+ }
+
+ if(Result == TRUE)
+ {
+ Result = FreeLibrary(hLibrary);
+ if(Result == FALSE)
+ {
+ hLibrary = 0;
+ }
+ }
+ }
+
+ return hLibrary;
+}
+
+NTSTATUS WINAPI
+User32CallClientLoadLibraryFromKernel(PVOID Arguments, ULONG ArgumentLength)
+{
+ HINSTANCE Result;
+ PCLIENT_LOAD_LIBRARY_ARGUMENTS Argument;
+
+ /* Retireve the callback parameters */
+ Argument = (PCLIENT_LOAD_LIBRARY_ARGUMENTS)Arguments;
+ if(Argument->strLibraryName.Buffer != NULL)
+ {
+ Argument->strLibraryName.Buffer = (PWCHAR)((ULONG_PTR)Argument->strLibraryName.Buffer + (ULONG_PTR)Argument);
+ }
+ if(Argument->strInitFuncName.Buffer != NULL)
+ {
+ Argument->strInitFuncName.Buffer = (PWCHAR)((ULONG_PTR)Argument->strInitFuncName.Buffer + (ULONG_PTR)Argument);
+ }
+
+ /* Call the implementation of the callback */
+ Result = ClientLoadLibrary(&Argument->strLibraryName,
+ &Argument->strInitFuncName,
+ Argument->Unload,
+ Argument->ApiHook);
+
+ return ZwCallbackReturn(&Result, sizeof(HINSTANCE), STATUS_SUCCESS);
+}
+