Codebase list golang-golang-x-sys / f9bc61c
windows: add resource extraction functions These functions make it possible to read executable resource information at runtime. Change-Id: I00f260199ecda8daeb3417eaa9c02198663063b7 Reviewed-on: https://go-review.googlesource.com/c/sys/+/298173 Trust: Jason A. Donenfeld <Jason@zx2c4.com> Trust: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Jason A. Donenfeld 3 years ago
4 changed file(s) with 163 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
88 import (
99 errorspkg "errors"
1010 "fmt"
11 "runtime"
1112 "sync"
1213 "syscall"
1314 "time"
383384 //sys getThreadPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetThreadPreferredUILanguages
384385 //sys getUserPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetUserPreferredUILanguages
385386 //sys getSystemPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetSystemPreferredUILanguages
387 //sys findResource(module Handle, name uintptr, resType uintptr) (resInfo Handle, err error) = kernel32.FindResourceW
388 //sys SizeofResource(module Handle, resInfo Handle) (size uint32, err error) = kernel32.SizeofResource
389 //sys LoadResource(module Handle, resInfo Handle) (resData Handle, err error) = kernel32.LoadResource
390 //sys LockResource(resData Handle) (addr uintptr, err error) = kernel32.LockResource
386391
387392 // Process Status API (PSAPI)
388393 //sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses
15771582 func (s *UNICODE_STRING) String() string {
15781583 return UTF16ToString(s.Slice())
15791584 }
1585
1586 // FindResource resolves a resource of the given name and resource type.
1587 func FindResource(module Handle, name, resType ResourceIDOrString) (Handle, error) {
1588 var namePtr, resTypePtr uintptr
1589 var name16, resType16 *uint16
1590 var err error
1591 resolvePtr := func(i interface{}, keep **uint16) (uintptr, error) {
1592 switch v := i.(type) {
1593 case string:
1594 *keep, err = UTF16PtrFromString(v)
1595 if err != nil {
1596 return 0, err
1597 }
1598 return uintptr(unsafe.Pointer(*keep)), nil
1599 case ResourceID:
1600 return uintptr(v), nil
1601 }
1602 return 0, errorspkg.New("parameter must be a ResourceID or a string")
1603 }
1604 namePtr, err = resolvePtr(name, &name16)
1605 if err != nil {
1606 return 0, err
1607 }
1608 resTypePtr, err = resolvePtr(resType, &resType16)
1609 if err != nil {
1610 return 0, err
1611 }
1612 resInfo, err := findResource(module, namePtr, resTypePtr)
1613 runtime.KeepAlive(name16)
1614 runtime.KeepAlive(resType16)
1615 return resInfo, err
1616 }
1617
1618 func LoadResourceData(module, resInfo Handle) (data []byte, err error) {
1619 size, err := SizeofResource(module, resInfo)
1620 if err != nil {
1621 return
1622 }
1623 resData, err := LoadResource(module, resInfo)
1624 if err != nil {
1625 return
1626 }
1627 ptr, err := LockResource(resData)
1628 if err != nil {
1629 return
1630 }
1631 h := (*unsafeheader.Slice)(unsafe.Pointer(&data))
1632 h.Data = unsafe.Pointer(ptr)
1633 h.Len = int(size)
1634 h.Cap = int(size)
1635 return
1636 }
44 package windows_test
55
66 import (
7 "bytes"
78 "debug/pe"
89 "errors"
910 "fmt"
561562 t.Errorf("expected os.Executable() to return same value as peb.Ldr.{entry}.FullDllName - want %#q; got %#q", osPath, pebPath)
562563 }
563564 }
565
566 func TestResourceExtraction(t *testing.T) {
567 system32, err := windows.GetSystemDirectory()
568 if err != nil {
569 t.Errorf("unable to find system32 directory: %v", err)
570 }
571 cmd, err := windows.LoadLibrary(filepath.Join(system32, "cmd.exe"))
572 if err != nil {
573 t.Errorf("unable to load cmd.exe: %v", err)
574 }
575 defer windows.FreeLibrary(cmd)
576 rsrc, err := windows.FindResource(cmd, windows.CREATEPROCESS_MANIFEST_RESOURCE_ID, windows.RT_MANIFEST)
577 if err != nil {
578 t.Errorf("unable to find cmd.exe manifest resource: %v", err)
579 }
580 manifest, err := windows.LoadResourceData(cmd, rsrc)
581 if err != nil {
582 t.Errorf("unable to load cmd.exe manifest resource data: %v", err)
583 }
584 if !bytes.Contains(manifest, []byte("</assembly>")) {
585 t.Errorf("did not find </assembly> in manifest")
586 }
587 }
25992599 SECURITY_SQOS_PRESENT = 0x100000
26002600 SECURITY_VALID_SQOS_FLAGS = 0x1f0000
26012601 )
2602
2603 // ResourceID represents a 16-bit resource identifier, traditionally created with the MAKEINTRESOURCE macro.
2604 type ResourceID uint16
2605
2606 // ResourceIDOrString must be either a ResourceID, to specify a resource or resource type by ID,
2607 // or a string, to specify a resource or resource type by name.
2608 type ResourceIDOrString interface{}
2609
2610 // Predefined resource names and types.
2611 var (
2612 // Predefined names.
2613 CREATEPROCESS_MANIFEST_RESOURCE_ID ResourceID = 1
2614 ISOLATIONAWARE_MANIFEST_RESOURCE_ID ResourceID = 2
2615 ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID ResourceID = 3
2616 ISOLATIONPOLICY_MANIFEST_RESOURCE_ID ResourceID = 4
2617 ISOLATIONPOLICY_BROWSER_MANIFEST_RESOURCE_ID ResourceID = 5
2618 MINIMUM_RESERVED_MANIFEST_RESOURCE_ID ResourceID = 1 // inclusive
2619 MAXIMUM_RESERVED_MANIFEST_RESOURCE_ID ResourceID = 16 // inclusive
2620
2621 // Predefined types.
2622 RT_CURSOR ResourceID = 1
2623 RT_BITMAP ResourceID = 2
2624 RT_ICON ResourceID = 3
2625 RT_MENU ResourceID = 4
2626 RT_DIALOG ResourceID = 5
2627 RT_STRING ResourceID = 6
2628 RT_FONTDIR ResourceID = 7
2629 RT_FONT ResourceID = 8
2630 RT_ACCELERATOR ResourceID = 9
2631 RT_RCDATA ResourceID = 10
2632 RT_MESSAGETABLE ResourceID = 11
2633 RT_GROUP_CURSOR ResourceID = 12
2634 RT_GROUP_ICON ResourceID = 14
2635 RT_VERSION ResourceID = 16
2636 RT_DLGINCLUDE ResourceID = 17
2637 RT_PLUGPLAY ResourceID = 19
2638 RT_VXD ResourceID = 20
2639 RT_ANICURSOR ResourceID = 21
2640 RT_ANIICON ResourceID = 22
2641 RT_HTML ResourceID = 23
2642 RT_MANIFEST ResourceID = 24
2643 )
204204 procFindNextFileW = modkernel32.NewProc("FindNextFileW")
205205 procFindNextVolumeMountPointW = modkernel32.NewProc("FindNextVolumeMountPointW")
206206 procFindNextVolumeW = modkernel32.NewProc("FindNextVolumeW")
207 procFindResourceW = modkernel32.NewProc("FindResourceW")
207208 procFindVolumeClose = modkernel32.NewProc("FindVolumeClose")
208209 procFindVolumeMountPointClose = modkernel32.NewProc("FindVolumeMountPointClose")
209210 procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers")
276277 procIsWow64Process2 = modkernel32.NewProc("IsWow64Process2")
277278 procLoadLibraryExW = modkernel32.NewProc("LoadLibraryExW")
278279 procLoadLibraryW = modkernel32.NewProc("LoadLibraryW")
280 procLoadResource = modkernel32.NewProc("LoadResource")
279281 procLocalAlloc = modkernel32.NewProc("LocalAlloc")
280282 procLocalFree = modkernel32.NewProc("LocalFree")
281283 procLockFileEx = modkernel32.NewProc("LockFileEx")
284 procLockResource = modkernel32.NewProc("LockResource")
282285 procMapViewOfFile = modkernel32.NewProc("MapViewOfFile")
283286 procMoveFileExW = modkernel32.NewProc("MoveFileExW")
284287 procMoveFileW = modkernel32.NewProc("MoveFileW")
325328 procSetStdHandle = modkernel32.NewProc("SetStdHandle")
326329 procSetVolumeLabelW = modkernel32.NewProc("SetVolumeLabelW")
327330 procSetVolumeMountPointW = modkernel32.NewProc("SetVolumeMountPointW")
331 procSizeofResource = modkernel32.NewProc("SizeofResource")
328332 procSleepEx = modkernel32.NewProc("SleepEx")
329333 procTerminateJobObject = modkernel32.NewProc("TerminateJobObject")
330334 procTerminateProcess = modkernel32.NewProc("TerminateProcess")
17461750 return
17471751 }
17481752
1753 func findResource(module Handle, name uintptr, resType uintptr) (resInfo Handle, err error) {
1754 r0, _, e1 := syscall.Syscall(procFindResourceW.Addr(), 3, uintptr(module), uintptr(name), uintptr(resType))
1755 resInfo = Handle(r0)
1756 if resInfo == 0 {
1757 err = errnoErr(e1)
1758 }
1759 return
1760 }
1761
17491762 func FindVolumeClose(findVolume Handle) (err error) {
17501763 r1, _, e1 := syscall.Syscall(procFindVolumeClose.Addr(), 1, uintptr(findVolume), 0, 0)
17511764 if r1 == 0 {
23702383 return
23712384 }
23722385
2386 func LoadResource(module Handle, resInfo Handle) (resData Handle, err error) {
2387 r0, _, e1 := syscall.Syscall(procLoadResource.Addr(), 2, uintptr(module), uintptr(resInfo), 0)
2388 resData = Handle(r0)
2389 if resData == 0 {
2390 err = errnoErr(e1)
2391 }
2392 return
2393 }
2394
23732395 func LocalAlloc(flags uint32, length uint32) (ptr uintptr, err error) {
23742396 r0, _, e1 := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(flags), uintptr(length), 0)
23752397 ptr = uintptr(r0)
23912413 func LockFileEx(file Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error) {
23922414 r1, _, e1 := syscall.Syscall6(procLockFileEx.Addr(), 6, uintptr(file), uintptr(flags), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped)))
23932415 if r1 == 0 {
2416 err = errnoErr(e1)
2417 }
2418 return
2419 }
2420
2421 func LockResource(resData Handle) (addr uintptr, err error) {
2422 r0, _, e1 := syscall.Syscall(procLockResource.Addr(), 1, uintptr(resData), 0, 0)
2423 addr = uintptr(r0)
2424 if addr == 0 {
23942425 err = errnoErr(e1)
23952426 }
23962427 return
28092840 return
28102841 }
28112842
2843 func SizeofResource(module Handle, resInfo Handle) (size uint32, err error) {
2844 r0, _, e1 := syscall.Syscall(procSizeofResource.Addr(), 2, uintptr(module), uintptr(resInfo), 0)
2845 size = uint32(r0)
2846 if size == 0 {
2847 err = errnoErr(e1)
2848 }
2849 return
2850 }
2851
28122852 func SleepEx(milliseconds uint32, alertable bool) (ret uint32) {
28132853 var _p0 uint32
28142854 if alertable {