// LoadDLL loads the named DLL file into memory.//// If name is not an absolute path and is not a known system DLL used by// Go, Windows will search for the named DLL in many locations, causing// potential DLL preloading attacks.//// Use LazyDLL in golang.org/x/sys/windows for a secure way to// load system DLLs.funcLoadDLL(namestring)(*DLL,error){namep,err:=UTF16PtrFromString(name)iferr!=nil{returnnil,err}varhuintptrvareErrnoifsysdll.IsSystemDLL[name]{h,e=loadsystemlibrary(namep)}else{h,e=loadlibrary(namep)}ife!=0{returnnil,&DLLError{Err:e,ObjName:name,Msg:"Failed to load "+name+": "+e.Error(),}}d:=&DLL{Name:name,Handle:Handle(h),}returnd,nil}
// A LazyDLL implements access to a single DLL.// It will delay the load of the DLL until the first// call to its Handle method or to one of its// LazyProc's Addr method.//// LazyDLL is subject to the same DLL preloading attacks as documented// on LoadDLL.//// Use LazyDLL in golang.org/x/sys/windows for a secure way to// load system DLLs.typeLazyDLLstruct{musync.Mutexdll*DLL// non nil once DLL is loadedNamestring}// Load loads DLL file d.Name into memory. It returns an error if fails.// Load will not try to load DLL, if it is already loaded into memory.func(d*LazyDLL)Load()error{// Non-racy version of:// if d.dll == nil {ifatomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll)))==nil{d.mu.Lock()deferd.mu.Unlock()ifd.dll==nil{dll,e:=LoadDLL(d.Name)ife!=nil{returne}// Non-racy version of:// d.dll = dllatomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll)),unsafe.Pointer(dll))}}returnnil}// mustLoad is like Load but panics if search fails.func(d*LazyDLL)mustLoad(){e:=d.Load()ife!=nil{panic(e)}}// Handle returns d's module handle.func(d*LazyDLL)Handle()uintptr{d.mustLoad()returnuintptr(d.dll.Handle)}// NewProc returns a LazyProc for accessing the named procedure in the DLL d.func(d*LazyDLL)NewProc(namestring)*LazyProc{return&LazyProc{l:d,Name:name}}// NewLazyDLL creates new LazyDLL associated with DLL file.funcNewLazyDLL(namestring)*LazyDLL{return&LazyDLL{Name:name}}
// LoadDLL loads DLL file into memory.//// Warning: using LoadDLL without an absolute path name is subject to// DLL preloading attacks. To safely load a system DLL, use LazyDLL// with System set to true, or use LoadLibraryEx directly.funcLoadDLL(namestring)(dll*DLL,errerror){namep,err:=UTF16PtrFromString(name)iferr!=nil{returnnil,err}h,e:=syscall_loadlibrary(namep)ife!=0{returnnil,&DLLError{Err:e,ObjName:name,Msg:"Failed to load "+name+": "+e.Error(),}}d:=&DLL{Name:name,Handle:h,}returnd,nil}
// A LazyDLL implements access to a single DLL.// It will delay the load of the DLL until the first// call to its Handle method or to one of its// LazyProc's Addr method.typeLazyDLLstruct{Namestring// System determines whether the DLL must be loaded from the// Windows System directory, bypassing the normal DLL search// path.Systemboolmusync.Mutexdll*DLL// non nil once DLL is loaded}// Load loads DLL file d.Name into memory. It returns an error if fails.// Load will not try to load DLL, if it is already loaded into memory.func(d*LazyDLL)Load()error{// Non-racy version of:// if d.dll != nil {ifatomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll)))!=nil{returnnil}d.mu.Lock()deferd.mu.Unlock()ifd.dll!=nil{returnnil}// kernel32.dll is special, since it's where LoadLibraryEx comes from.// The kernel already special-cases its name, so it's always// loaded from system32.vardll*DLLvarerrerrorifd.Name=="kernel32.dll"{dll,err=LoadDLL(d.Name)}else{dll,err=loadLibraryEx(d.Name,d.System)}iferr!=nil{returnerr}// Non-racy version of:// d.dll = dllatomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.dll)),unsafe.Pointer(dll))returnnil}// mustLoad is like Load but panics if search fails.func(d*LazyDLL)mustLoad(){e:=d.Load()ife!=nil{panic(e)}}// Handle returns d's module handle.func(d*LazyDLL)Handle()uintptr{d.mustLoad()returnuintptr(d.dll.Handle)}// NewProc returns a LazyProc for accessing the named procedure in the DLL d.func(d*LazyDLL)NewProc(namestring)*LazyProc{return&LazyProc{l:d,Name:name}}// NewLazyDLL creates new LazyDLL associated with DLL file.funcNewLazyDLL(namestring)*LazyDLL{return&LazyDLL{Name:name}}// NewLazySystemDLL is like NewLazyDLL, but will only// search Windows System directory for the DLL if name is// a base name (like "advapi32.dll").funcNewLazySystemDLL(namestring)*LazyDLL{return&LazyDLL{Name:name,System:true}}