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]

Reply via email to