New topic: Unicode API calls failing; Ansi counterparts succeed
<http://forums.realsoftware.com/viewtopic.php?t=32165> Page 1 of 1 [ 1 post ] Previous topic | Next topic Author Message computerfreaker Post subject: Unicode API calls failing; Ansi counterparts succeedPosted: Sun Jan 24, 2010 11:32 am Joined: Thu Mar 05, 2009 1:03 pm Posts: 1507 Location: USA Well, I'm running up against yet another set of troublesome API calls, this time with a twist. The non-Unicode versions of these calls work, but the Unicode versions fail or even crash my app. Probably an incorrect declare or two, but consulting MSDN is about as helpful as consulting my goldfish... The API calls in question are ShellExecuteEx (ShellExecuteExA works but ShellExecuteExW doesn't) and something related to a keyboard hook. Not sure what's going wrong with the keyboard hook, but pressing a key crashes my app. Here are the relevant declarations: Code: //Function RunAsAdmin(extends File As FolderItem, hWndOwner As Integer, Parameters As String = "") As Integer Soft Declare Function ShellExecuteExA Lib "shell32" (ByRef SEI As SHELLEXECUTEINFOA) As Integer Soft Declare Function ShellExecuteExW Lib "shell32" (ByRef SEI As SHELLEXECUTEINFOW) As Integer Const SEE_MASK_NOCLOSEPROCESS = &H40 'Const SEE_MASK_FLAG_NO_UI = &H400 dim SEIA As SHELLEXECUTEINFOA, SEIW As SHELLEXECUTEINFOW if System.IsFunctionAvailable("ShellExecuteExW", "shell32") then SEIW.cbSize = SEIW.Size SEIW.fMask = SEE_MASK_NOCLOSEPROCESS SEIW.hWnd = hWndOwner SEIW.lpVerb = "runas" SEIW.lpFile = File.AbsolutePath if Parameters <> "" then SEIW.lpParameters = Parameters Return ShellExecuteExA(SEIA) else SEIA.cbSize = SEIA.Size SEIA.fMask = SEE_MASK_NOCLOSEPROCESS SEIA.hWnd = hWndOwner SEIA.lpVerb = "runas" SEIA.lpFile = File.AbsolutePath if Parameters <> "" then SEIA.lpParameters = Parameters Return ShellExecuteExA(SEIA) end if Code: //Structure SHELLEXECUTEINFOA cbSize As Integer fMask As Integer hWnd As Integer lpVerb As CString lpFile As CString lpParameters As CString lpDirectory As CString nShow As Integer hInstApp As Integer lpIDList As Integer lpClass As Integer hkeyClass As Integer dwHotKey As Integer hIcon As Integer hProcess As Integer Code: //Structure SHELLEXECUTEINFOW cbSize As Integer fMask As Integer hWnd As Integer lpVerb As WString lpFile As WString lpParameters As WString lpDirectory As WString nShow As Integer hInstApp As Integer lpIDList As Integer lpClass As Integer hkeyClass As Integer dwHotKey As Integer hIcon As Integer hProcess As Integer ShellExecuteExA correctly displays the "Run as" dialog box; ShellExecuteExW apparently does nothing. I've checked the debugger and the SHELLEXECUTEINFOW structure appears to be correctly populated. Now for the real pain - the keyboard hook. There are three different things that could be malfunctioning here; two of them look OK, and I can't get the debugger into the third because the app crashes before the first line of the method is executed (I know, because I've set a breakpoint on the first line of the method - the crash comes before the debugger stops). Code: //Function App.hInstance() As Integer Soft Declare Function GetModuleHandleA lib "kernel32" (lpModuleName as Integer) as Integer Soft Declare Function GetModuleHandleW lib "kernel32" (lpModuleName as Integer) as Integer if System.IsFunctionAvailable("GetModuleHandleW", "kernel32") then Return GetModuleHandleW(0) else Return GetModuleHandleA(0) end if This checks out; regardless of which API call was used, a reasonable hInstance value is returned. Code: //Sub CreateKeyboardHook() //pre: none //post: tries to hook the keyboard, then checks to see if the keyboard hook exists or not Soft Declare Function SetWindowsHookExA lib "user32" (ByVal idHook as Integer, ByVal lpfn as Ptr, ByVal hmod as Integer, ByVal dwThreadId as Integer) as Integer Soft Declare Function SetWindowsHookExW lib "user32" (ByVal idHook as Integer, ByVal lpfn as Ptr, ByVal hmod as Integer, ByVal dwThreadId as Integer) as Integer Const WH_KEYBOARD_LL = 13 if System.IsFunctionAvailable("SetWindowsHookExW", "user32") then //hook into the keyboard messages; the messages will be sent to KeyboardCallback, since that's the function whose address //we're sending to the API KeyboardHandle = SetWindowsHookExW(WH_KEYBOARD_LL, AddressOf KeyboardCallback, app.hInstance, 0) else KeyboardHandle = SetWindowsHookExA(WH_KEYBOARD_LL, AddressOf KeyboardCallback, app.hInstance, 0) end if if not CheckHooked() then //make sure we've successfully hooked into the keyboard; if we haven't, we've got a big problem WriteErrorToLog("Error: hooking keyboard failed!") end if This also checks out; I was able to walk through this in the debugger, and CheckHooked (a simple method that checks the value of KeyboardHandle) returned True. All seems to be well up to this point, but something's screwy; this next method crashes, invariably, as soon as a key is pressed. As I mentioned, I can't get the debugger in here. Code: //Function KeyboardCallback(ByVal Code As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer //pre: Windows passed us a keyboard message //post: handles the keyboard message based on the blocking rules in IsHooked //after we create the keyboard hook in CreateKeyboardHook(), all keyboard messages will be passed here Soft Declare Function CallNextHookEx lib "user32" (ByVal hHook as Integer, ByVal nCode as Integer, ByVal wParam as Integer, ByVal lParam as Integer) as Integer Soft Declare Sub CopyMemory lib "kernel32" Alias "RtlMoveMemory" (pDest as Ptr, pSource as Integer, cb as Integer) Dim HookStruct as new MemoryBlock(20) //Here's the structure of KBDLLHOOKSTRUCT, which HookStruct is representing: //Structure KBDLLHOOKSTRUCT //vkCode as Integer //scanCode as Integer //flags as Integer //time as Integer //dwExtraInfo as Integer //End Structure Const HC_ACTION = 0 if Code = HC_ACTION then //copy the keyboard data out of the lParam, which is a pointer CopyMemory(HookStruct, lParam, HookStruct.Size) if IsHooked(HookStruct) then //we've blocked the current keyboard key combo; don't let it get by Return 1 //tell Windows we're handling the keyboard message; due to the way the Windows process messaging system is implemented, the message won't be passed to any other applications end if end if Return CallNextHookEx(KeyboardHandle, Code, wParam, lParam) //let the default handler (presumably the OS) handle the keyboard message IsHooked just checks the key against a list of keys to block and returns True or False appropriately; this method is never called because the crash happens too soon. The important (and baffling) thing here is that the Ansi calls work but the Unicode calls fail; my computer is running Windows XP Pro SP3, so it definitely has Unicode support. Another Unicode call (the only other one I can even try right now, since the keyboard hook crash invariably stops me from getting to call anything else), CreateMutexW, works just fine. Any thoughts? Thanks in advance! computerfreaker _________________ With great power comes great responsibility. Learn something new every day, and the rest will take care of itself. Life is a journey, not a destination. Enjoy the trip! Top Display posts from previous: All posts1 day7 days2 weeks1 month3 months6 months1 year Sort by AuthorPost timeSubject AscendingDescending Page 1 of 1 [ 1 post ] -- Over 1500 classes with 29000 functions in one REALbasic plug-in collection. The Monkeybread Software Realbasic Plugin v9.3. http://www.monkeybreadsoftware.de/realbasic/plugins.shtml [email protected]
