func (t *Thread) writeMemory(addr uintptr, data []byte) (int, error) { var ( vmData = C.LPCVOID(unsafe.Pointer(&data[0])) vmAddr = C.LPVOID(addr) length = C.SIZE_T(len(data)) count C.SIZE_T ) ret := C.WriteProcessMemory(C.HANDLE(t.dbp.os.hProcess), vmAddr, vmData, length, &count) if ret == C.FALSE { return int(count), fmt.Errorf("could not write memory") } return int(count), nil }
func (t *Thread) readMemory(addr uintptr, size int) ([]byte, error) { if size == 0 { return nil, nil } var ( buf = make([]byte, size) vmData = C.LPVOID(unsafe.Pointer(&buf[0])) vmAddr = C.LPCVOID(addr) length = C.SIZE_T(size) count C.SIZE_T ) ret := C.ReadProcessMemory(C.HANDLE(t.dbp.os.hProcess), vmAddr, vmData, length, &count) if ret == C.FALSE { return nil, fmt.Errorf("could not read memory") } return buf, nil }
// Sorts 'count' child elements starting at index 'start'. Uses comparator to define the // order. Comparator should return -1, or 0, or 1 to indicate less, equal or greater func (e *Element) SortChildrenRange(start, count uint, comparator func(*Element, *Element) int) { end := start + count arg := uintptr(unsafe.Pointer(&comparator)) if ret := C.HTMLayoutSortElements(e.handle, C.UINT(start), C.UINT(end), (*[0]byte)(unsafe.Pointer(goElementComparator)), C.LPVOID(arg)); ret != HLDOM_OK { domPanic(ret, "Failed to sort elements") } }
func (e *Element) Select(selector string) []*Element { szSelector := C.CString(selector) defer C.free(unsafe.Pointer(szSelector)) results := make([]*Element, 0, 32) if ret := C.HTMLayoutSelectElements(e.handle, (*C.CHAR)(szSelector), (*[0]byte)(unsafe.Pointer(goSelectCallback)), C.LPVOID(unsafe.Pointer(&results))); ret != HLDOM_OK { domPanic(ret, "Failed to select dom elements, selector: '", selector, "'") } return results }
func (e *Element) DetachHandler(handler *EventHandler) { tag := uintptr(unsafe.Pointer(handler)) if attachedHandlers, exists := eventHandlers[e.handle]; exists { if _, exists := attachedHandlers[handler]; exists { if ret := C.HTMLayoutDetachEventHandler(e.handle, (*[0]byte)(unsafe.Pointer(goElementProc)), C.LPVOID(tag)); ret != HLDOM_OK { domPanic(ret, "Failed to detach event handler from element") } delete(attachedHandlers, handler) if len(attachedHandlers) == 0 { delete(eventHandlers, e.handle) } return } } panic("cannot detach, handler was not registered") }
func (e *Element) AttachHandler(handler *EventHandler) { attachedHandlers, hasAttachments := eventHandlers[e.handle] if hasAttachments { if _, exists := attachedHandlers[handler]; exists { // This exact event handler is already attached to this exact element. return } } // Don't let the caller disable ATTACH/DETACH events, otherwise we // won't know when to throw out our event handler object subscription := handler.Subscription() subscription &= ^uint32(DISABLE_INITIALIZATION & 0xffffffff) tag := uintptr(unsafe.Pointer(handler)) if subscription == HANDLE_ALL { if ret := C.HTMLayoutAttachEventHandler(e.handle, (*[0]byte)(unsafe.Pointer(goElementProc)), C.LPVOID(tag)); ret != HLDOM_OK { domPanic(ret, "Failed to attach event handler to element") } } else { if ret := C.HTMLayoutAttachEventHandlerEx(e.handle, (*[0]byte)(unsafe.Pointer(goElementProc)), C.LPVOID(tag), C.UINT(subscription)); ret != HLDOM_OK { domPanic(ret, "Failed to attach event handler to element") } } if !hasAttachments { eventHandlers[e.handle] = make(map[*EventHandler]bool, 8) } eventHandlers[e.handle][handler] = true }
// This is the same as AttachHandler, except that behaviors are singleton instances stored // in a master map. They may be shared among many elements since they have no state. // The only reason we keep a separate set of the behaviors is so that the event handler // dispatch method can tell if an event handler is a behavior or a regular handler. func (e *Element) attachBehavior(handler *EventHandler) { tag := uintptr(unsafe.Pointer(handler)) if subscription := handler.Subscription(); subscription == HANDLE_ALL { if ret := C.HTMLayoutAttachEventHandler(e.handle, (*[0]byte)(unsafe.Pointer(goElementProc)), C.LPVOID(tag)); ret != HLDOM_OK { domPanic(ret, "Failed to attach event handler to element") } } else { if ret := C.HTMLayoutAttachEventHandlerEx(e.handle, (*[0]byte)(unsafe.Pointer(goElementProc)), C.LPVOID(tag), C.UINT(subscription)); ret != HLDOM_OK { domPanic(ret, "Failed to attach event handler to element") } } }
// Finalizer method, only to be called from Release or by // the Go runtime func (e *Element) finalize() { // Detach handlers if attachedHandlers, hasHandlers := eventHandlers[e.handle]; hasHandlers { for handler := range attachedHandlers { tag := uintptr(unsafe.Pointer(handler)) C.HTMLayoutDetachEventHandler(e.handle, (*[0]byte)(unsafe.Pointer(goElementProc)), C.LPVOID(tag)) } delete(eventHandlers, e.handle) } // Release the underlying htmlayout handle unuse(e.handle) e.handle = BAD_HELEMENT }
func AttachNotifyHandler(hwnd uint32, handler *NotifyHandler) { key := uintptr(hwnd) // Overwrite if it exists notifyHandlers[key] = handler C.HTMLayoutSetCallback(C.HWND(C.HANDLE(key)), (*[0]byte)(unsafe.Pointer(goNotifyProc)), C.LPVOID(key)) }
func DetachWindowEventHandler(hwnd uint32) { key := uintptr(hwnd) if handler, exists := windowEventHandlers[hwnd]; exists { tag := uintptr(unsafe.Pointer(handler)) if ret := C.HTMLayoutWindowDetachEventHandler(C.HWND(C.HANDLE(key)), (*[0]byte)(unsafe.Pointer(goElementProc)), C.LPVOID(tag)); ret != HLDOM_OK { domPanic(ret, "Failed to detach event handler from window") } delete(windowEventHandlers, hwnd) } }
func AttachWindowEventHandler(hwnd uint32, handler *EventHandler) { key := uintptr(hwnd) tag := uintptr(unsafe.Pointer(handler)) if _, exists := windowEventHandlers[hwnd]; exists { if ret := C.HTMLayoutWindowDetachEventHandler(C.HWND(C.HANDLE(key)), (*[0]byte)(unsafe.Pointer(goElementProc)), C.LPVOID(tag)); ret != HLDOM_OK { domPanic(ret, "Failed to detach event handler from window before adding the new one") } } // Overwrite if it exists windowEventHandlers[hwnd] = handler // Don't let the caller disable ATTACH/DETACH events, otherwise we // won't know when to throw out our event handler object subscription := handler.Subscription() subscription &= ^uint32(DISABLE_INITIALIZATION & 0xffffffff) if ret := C.HTMLayoutWindowAttachEventHandler(C.HWND(C.HANDLE(key)), (*[0]byte)(unsafe.Pointer(goElementProc)), C.LPVOID(tag), C.UINT(subscription)); ret != HLDOM_OK { domPanic(ret, "Failed to attach event handler to window") } }
// Creates the window. This function expects not to be called on a ContextThread func (wi *windowInternal) initialize(monitor *Monitor, mode VideoMode, title string, style WindowStyle) ThreadError { // Compute position and size screenDC := C.GetDC(nil) width := C.int(mode.Width) height := C.int(mode.Height) left := (C.GetDeviceCaps(screenDC, C.HORZRES) - width) / 2 top := (C.GetDeviceCaps(screenDC, C.VERTRES) - height) / 2 C.ReleaseDC(nil, screenDC) // Choose the window style according to the Style parameter win32Style := C.DWORD(C.WS_VISIBLE) if style == WindowStyleNone { win32Style |= C.WS_POPUP } else { if style&WindowStyleTitlebar != 0 { win32Style |= C.WS_CAPTION | C.WS_MINIMIZEBOX } if style&WindowStyleResize != 0 { win32Style |= C.WS_THICKFRAME | C.WS_MAXIMIZEBOX } if style&WindowStyleClose != 0 { win32Style |= C.WS_SYSMENU } } // In windowed mode, adjust width and height so that window will have the requested client area fullscreen := style&WindowStyleFullscreen != 0 if !fullscreen { rectangle := C.RECT{ left: C.LONG(left), top: C.LONG(top), right: C.LONG(left + width), bottom: C.LONG(top + height), } C.__AdjustWindowRect(&rectangle, win32Style, C.FALSE) left = C.int(rectangle.left) top = C.int(rectangle.top) width = C.int(rectangle.right - rectangle.left) height = C.int(rectangle.bottom - rectangle.top) } wTitle, _ := utf16Convert(title) wi.window.Handle = C.CreateWindowExW(0, className, wTitle, win32Style, left, top, width, height, nil, nil, windowClass.hInstance, C.LPVOID(wi)) // Switch to fullscreen if requested if fullscreen { wi.switchToFullscreen(monitor, mode) } return nil }