Accessing CPL applets - Windows Mobile Development and Hacking General

I am trying to access some control panel applets from
my application. This works fine for the most applets.
I use the ctlpnl.exe process to display the applets like:
CreateProcess(_T("ctlpnl.exe"), _T("cplmain.cpl,27,0"), NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pi);
For some reason I cannot display the applet for USB to PC connection (ID 27 in WM5, 28 in WM6).
In WM6 I have the same problem with the encryption applet (ID 27). All other applets work. The applet is displayed for 1 second, I can see
the title in the window and then it disappears.
Has anybody made the same experiences? Is there a workaround for this?
Is this a bug in ctlpnl.exe or in WM5/6?
Thanks for any help.
Houser

Try calling it independent of ctlpnl.exe:
Do a LoadLibrary on the .cpl file
Call GetProcAddress to get a pointer to the CPlApplet function
Call CPlApplet with msg == CPL_INIT
Call CPlApplet with msg == CPL_GETCOUNT to get the # of applets supported by the .cpl file
For each applet above (i = 0 to CPL_GETCOUNT - 1), call CPlApplet with msg == CPL_NEWINQUIRE, taking note of the lData value returned.
For the applet you want to launch, call CPlApplet with msg == CPL_DBLCLK, lParam1 == the applet #, lParam2 == the lData value from the previous step.
When you're done, call CPlApplet with msg == CPL_STOP.
I've done this in big Windows, but never on CE -- my read of the MSDN doc suggests it should work on WM 5/6.

Have already tried it this way but not with lData value when
calling CPL_DBLCLK. But the problem is still there. When I want to access
the cplmain.cpl applet with ID 27 (USB to PC connection) it does not work.
The other IDs (<27) work perfectly.
I do not know why! Arghhh!
Houser

Nobody has encounter same problems with CPL applets?
Houser

did you ever figure this out?
I am having same issues
Houser said:
I am trying to access some control panel applets from
my application. This works fine for the most applets.
I use the ctlpnl.exe process to display the applets like:
CreateProcess(_T("ctlpnl.exe"), _T("cplmain.cpl,27,0"), NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pi);
For some reason I cannot display the applet for USB to PC connection (ID 27 in WM5, 28 in WM6).
In WM6 I have the same problem with the encryption applet (ID 27). All other applets work. The applet is displayed for 1 second, I can see
the title in the window and then it disappears.
Has anybody made the same experiences? Is there a workaround for this?
Is this a bug in ctlpnl.exe or in WM5/6?
Thanks for any help.
Houser
Click to expand...
Click to collapse

Related

TAPI data calls.

1) Hi, we works with Pocket PC 2003 (Embedded Visual C++ 4.0). Our target is perform a data call over integrated cellular line. We read that the right mean is TAPI (XDA-Developers forum) because COM2 seem to be owned by RIL layer. We wrote a test program which handles a data call answer. We get the serial port handle returned by "lineGetID()" function for current data call, but when we try to use it through standard communication APIs ("WriteFile()" and "ReadFile()") it doesn't work (no data is read or write from port handle, but there aren't errors returned by APIs). Same code seems to work fine on a HP IPAQ 2210 with a Compact Flash GSM/GPRS card. How can we transfer data so?
2) We noticed a phone answering process is alive (CPROG.EXE) that takes calls' control. We kill this process when we make our tests, but it backs to life after some minutes. How can we take real calls' control?
3) Is the integrated cellular modem Hayes compatible? Is there a way to directly send AT commands to integrated cellular modem?
4) DCB structure "PortDCB" we pass to "SetCommState()" is the following:
PortDCB.DCBlength = sizeof (DCB);
PortDCB.BaudRate = 9600;
PortDCB.fBinary = TRUE;
PortDCB.fParity = TRUE;
PortDCB.fOutxCtsFlow = FALSE;
PortDCB.fOutxDsrFlow = FALSE;
PortDCB.fDtrControl = DTR_CONTROL_ENABLE;
PortDCB.fDsrSensitivity = FALSE;
PortDCB.fTXContinueOnXoff = TRUE;
PortDCB.fOutX = FALSE;
PortDCB.fInX = FALSE;
PortDCB.fErrorChar = FALSE;
PortDCB.fNull = FALSE;
PortDCB.fRtsControl = RTS_CONTROL_ENABLE;
PortDCB.fAbortOnError = FALSE;
PortDCB.ByteSize = 8;
PortDCB.Parity = NOPARITY;
PortDCB.StopBits = ONESTOPBIT;
Is it correct?
Can anybody help me?
Matthew
This DCB params seem do right job....
Code:
PortDCB.BaudRate = 115200;
PortDCB.fBinary = TRUE;
PortDCB.fParity = FALSE;
//PortDCB.fParity = TRUE;
PortDCB.fOutxCtsFlow = FALSE;
PortDCB.fOutxDsrFlow = FALSE;
PortDCB.fDtrControl = DTR_CONTROL_ENABLE;
PortDCB.fDsrSensitivity = FALSE;
//PortDCB.fDsrSensitivity = TRUE;
PortDCB.fTXContinueOnXoff = TRUE;
//PortDCB.fTXContinueOnXoff = FALSE;
PortDCB.fOutX = FALSE;
PortDCB.fInX = FALSE;
PortDCB.fErrorChar = FALSE;
PortDCB.fNull = FALSE;
PortDCB.fRtsControl = RTS_CONTROL_DISABLE;
PortDCB.fAbortOnError = FALSE;
PortDCB.ByteSize = 8;
PortDCB.Parity = NOPARITY;
PortDCB.StopBits = ONESTOPBIT;
problem one shuold be solved ...Hi
Your DCB parameters worked fine.
Hi Matthew.
Your parameters worked fine with my application, i was teting an IMate and you helped me a lot with my next product version.
Thank you.
Cesar Bremer Pinheiro
Bremer Serv. Emp. Ltda.
Raseac Division.
http://www.raseac.com.br
Dear Matthew,
Hi,
I created a similar application to make a call from one PPC to another using data link. The problem is my program couldn't detect incoming calls. Would you please help me solve this issue?
Do you have any source code that I can learn from it? Also which method did you use? TAPI? COM port? RIL?
I'm very confused. Please help....
Best regards,
A. Riazi
Why is your baudrate 115200 when a CSD connection through TAPI is only at 9600 ?
cause it's TAPI
you can't select bearer capabilities
if you wana select rate use RIL or direct access to COM-ports
mathews help!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
hi,
i am facing a similar problem cant send data through writefile api on cellular line
these r code snippets form my cod e
if(dwReturn =lineOpen (
g_hLineApp, // Usage handle for TAPI
g_dwCurrentLineID, // Cannot use the LINEMAPPER value
&g_CurrentLineInfo.hLine, // Line handle
g_CurrentLineInfo.dwAPIVersion,
// API version number
0, // Must set to zero for Windows CE
0, // No data passed back
LINECALLPRIVILEGE_NONE, // Can only make an outgoing call
0, // Media mode
NULL))
g_MakeCallRequestID = lineMakeCall (g_CurrentLineInfo.hLine,
&g_hCall,
szDialablePhoneNum,
0,
NULL);
dwRet =lineGetID(g_CurrentLineInfo.hLine, 0, 0, LINECALLSELECT_LINE, lpVarString,TEXT("comm/datamodem"));
till this its ok it returns a valid comm handle
after that it sends th data over the connected call but doesnt receive anythinga t the other end ...
the problem might be to give a call handle and LINECALLSELECT_CALL in linegteid func tion i tried it but when i use it fails saying cannot obtain the handle .......now i don understand whether its the problem of not obtaining a handle or whether linehandle will work but problem is in communication ...
plz help and add some code snippets for the communication
firstly have you set up the following...
LPLINECALLPARAMS CallParams;
CallParams=(LPLINECALLPARAMS)malloc(sizeof(LINECALLPARAMS)+1024);
memset(CallParams,0,sizeof(LINECALLPARAMS)+1024);
CallParams->dwTotalSize = sizeof(LINECALLPARAMS)+1024;
// This is where we configure the line for DATAMODEM usage.
//its important to note that if you attempt to make a call
//using LINEMEDIAMODE_DATAMODEM, the line must be opened in
//that way to begin with or nothing will happen. ie open lines
//corresponding to what you plan to makecall with.
CallParams->dwBearerMode = LINEBEARERMODE_VOICE;//over voice call
CallParams->dwMediaMode = LINEMEDIAMODE_DATAMODEM;//data transmition
//LINEMEDIAMODE_INTERACTIVEVOICE;//for voice
//specify that we only want to use a call that is not alreay in use.
//Otherwise it can take over calls that are in progress
CallParams->dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
//specify to use the first address
CallParams->dwAddressMode = LINEADDRESSMODE_ADDRESSID;
CallParams->dwAddressID = 0;
next check the line you want to use and make sure...
if(lpDevCaps->dwBearerModes & callModeData)//datamode
{
if(lpDevCaps->dwBearerModes & callModeVoice)
{
//then check the media mode
if(lpDevCaps->dwMediaModes & LINEMEDIAMODE_DATAMODEM)
{
if(lpDevCaps->dwMediaModes & LINEMEDIAMODE_INTERACTIVEVOICE)
{
//use it
}
}
}
}
next when you get an incoming call etc get the handle......
HANDLE myTapiManager::getHandle()
{
HANDLE hModem=NULL;
CString name="";
classType="comm/datamodem";
DWORD dwSize = sizeof(VARSTRING) + 2048;
DWORD dwRet = 0;
do
{
LPVARSTRING lpVarString = (LPVARSTRING) new BYTE[dwSize];
lpVarString->dwTotalSize = dwSize;
//the commented out values are what microsoft seem to say
//but cause it to return no handle but only the device class name
dwRet = ::lineGetID(/*hOpenedLine*/NULL, 0,hCall,LINECALLSELECT_CALL /*LINECALLSELECT_LINE*/, lpVarString,
classType);
if ( dwRet == 0 )
{
hModem= * (HANDLE*) ((char*) lpVarString + lpVarString->dwStringOffset);
name= * (LPTSTR) ((char*) lpVarString + lpVarString->dwStringOffset + sizeof(HANDLE));
if(hModem==NULL)
{
MessageBox(NULL,_T("null handle"),_T("handle"),MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
}
else
{
MessageBox(NULL,_T("non null handle, about to call init on port"),_T("handle"),MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
hSerialHandle=hModem;
//you must initialize the port but I do not show it here
initializeIOTimeOuts();
}
break;
}
else if ( dwRet == LINEERR_STRUCTURETOOSMALL )
{
dwSize = lpVarString->dwNeededSize;
delete lpVarString;
lpVarString = NULL;
continue;
}
else
{
// handle errors.........
//
hModem=NULL;
}
}
while (1);
return hModem;
}
this works for me. One problem you may be having is the timing. If you get the handle when the call is offering it will be useless. You must ensure that the call is connected, use the LINECALLSTATE_CONNECTED for this.
cprog dose not effect the opperation of your program, only its ui.
Have you looked at the zip I put in this post ?
http://forum.xda-developers.com/viewtopic.php?t=18978
It may help you with the sending part and getting a handle to Readfile/writefile.
I have never worked on the anwering side so I know nothing on that.
to answer the call that is offering, use LineAnswer. I have tried LinePickup but it has not done what I want. When using lineanswer be aware that the os has already set the number of rings it will ring before the call is actually answered after you answer it. It is normally changed through the phone settings but you can do it programatically if you wish.
Also, you have not mentioned what you are doing with regards to threads. The first time I tried using tapi I spent a lot of time avoiding using multiple threads but it is impracticle. A good number would be 1 for the ui 1 for the line status and 1 for data transfer. Getting your serial handle would the require carefull synchronization.
I have not found benefit in altering any of the port settings. The time-outs for the read/write can make a huge difference though.
Have you checked if there is a class name following the handle in the LPVARSTRING? I have found that if you are doing everything correct except the timing, the name is added but not the handle. This means that the name would be 4 places sooner than it should. In that case the name is in the place where the handle should be and the call still succeeded. Try writing to the port using a string instead of a handle and see how far you get(kidding). To test it just treat the handle you have got as if it where a string and put it in a messagebox. If you can read it then your timing is off.
Lastly your problem could come from how you are setting the api version. Have you been checking the errors generated after all your api calls. There are a lot for tapi that tell you most of what is going on. I have noticed that if you are using the event method for getting line state messages from tapi (ie the correct time to grab the handle) there is something wrong with the way the api version gets negotiated. The event method is part of tapi 2.0 i think so it should be expected that an api version of at least 2.0 is a good version to aim for. For win ce 3.0 docs say that 2.0 is fully supported and parts of 2.1. This is not what actually happens though, I have found that I can't get the event method to work at all (among other things) if I don't pass a min version of 1.1 and a max version of 1.3. This is bizar because by that input tapi should not use any features above 1.3 :?:
guys i ve been trying to set up call params
//Configure line device for a data modem
memset(&LineCallParams, 0, sizeof(LineCallParams));
LineCallParams.dwTotalSize = sizeof(LineCallParams);
LineCallParams.dwBearerMode = LINEBEARERMODE_VOICE;
LineCallParams.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
LineCallParams.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
//If multiple addresses on the line, use the first address
LineCallParams.dwAddressMode = LINEADDRESSMODE_ADDRESSID;
LineCallParams.dwAddressID = 0;
the problem is when i pass the lpparam instead of null it reaches to dialing the number and says disconnected: unreachable ..
There is no error while lineopen is passed with LINEMEDIAMODE_DATAMODEM as the 8th parameter i think it shoudl have given an error of media mode not supported at that point only ....but it didnt .....it opened the line fine
when i did not set the datamodem media mode in call params and rest remain as it is ..........the call works fine and is connected ....is it because the datacall facility is not supported and if it is not how can it be activated ....
lReturn = lineOpen(m_hLineApp, m_dwDeviceID, &m_hLine, m_dwAPIVersion, 0 , 0,
LINECALLPRIVILEGE_NONE, LINEMEDIAMODE_DATAMODEM, 0);
g_MakeCallRequestID = lineMakeCall (g_CurrentLineInfo.hLine,
&g_hCall,
szDialablePhoneNum,
0,
NULL); // NULL for default voice call
/**************************/
// lpCallParams);
Firstly, is the phone you are trying to dial a ppc. If yes... the ppc you wish to be the one that answers the call must have opened the line the same way as the dialing one, ie supporting data. If not then it will not even ring when a data call is offering and you will never know if your call was really made.
next look at lineopen.
long opnResult=lineOpen(hLineApp,
deviceID,
&hOpenedLine,
apiNegotiatedForUsedDevice,
0,//not used at all
1,//not used by tapi, but is passed back to this //application to help identify the source of the messages.
//in each line state message. It can be used
//to make sure the message is from a line
//opened by this app.
LINECALLPRIVILEGE_OWNER,// tells it can //accept calls.
LINEMEDIAMODE_DATAMODEM,
NULL);
almost the same but try LINECALLPRIVILEGE_OWNER. This must be set on the receiving end but I also set it on the dialing end.
If the media mode is not supported you will get an error message to tell so. That is the primary way my programs determine the identity of the line to use.
What is the device you are using? I have got bi-directional data transfer to work between ppc 2002 (xda I) and wm2003 se (xda mini). Before 2002 not as many features are supported.
also your call params may be too small
try adding a litle to the end
LPLINECALLPARAMS CallParams;
CallParams=(LPLINECALLPARAMS)malloc(sizeof(LINECALLPARAMS)+1024);
memset(CallParams,0,sizeof(LINECALLPARAMS)+1024);
CallParams->dwTotalSize = sizeof(LINECALLPARAMS)+1024;
.
.
.
.
and what about the number to dial in the call params
// Address to dial
//set its location to be after the normal end of the structure
CallParams->dwDisplayableAddressOffset = sizeof(LINECALLPARAMS);
CallParams->dwDisplayableAddressSize = strlen(szPhNumber);
strcpy((LPSTR)CallParams+sizeof(LINECALLPARAMS), szPhNumber));
then pass the szPhNumber into linemakecall, remember that ppc version
takes unicode.
i am trying to pass data from pocket pc to my pc
this is whole part
LPLINETRANSLATEOUTPUT lpTransOutput = NULL;
// Call translate address before dialing.
do
{
// Allocate memory for lpTransOutput.
if (!(lpTransOutput = (LPLINETRANSLATEOUTPUT) LocalAlloc (
LPTR,
dwSizeOfTransOut)))
{
ErrorBox(TEXT("translate fails "));
goto exit;
}
lpTransOutput->dwTotalSize = dwSizeOfTransOut;
if (dwReturn = lineTranslateAddress (
g_hLineApp, // Usage handle for TAPI
g_dwCurrentLineID, // Line device identifier
g_CurrentLineInfo.dwAPIVersion,
// Highest TAPI version supported
lpszPhoneNum, // Address to be translated
0, // Must be 0 for Windows CE
0, // No associated operations
lpTransOutput)) // Result of the address translation
{
ErrorBox(TEXT("lineTranslateAddress fails "));
goto exit;
}
if (lpTransOutput->dwNeededSize <= lpTransOutput->dwTotalSize)
break;
else
{
dwSizeOfTransOut = lpTransOutput->dwNeededSize;
LocalFree (lpTransOutput);
lpTransOutput = NULL;
}
} while (TRUE);
dwSizeOfCallParams += lpTransOutput->dwDisplayableStringSize;
if (!(lpCallParams = (LPLINECALLPARAMS) LocalAlloc (
LPTR,
dwSizeOfCallParams)))
{
ErrorBox(TEXT("lineTranslateAddress open fails "));
goto exit;
}
ZeroMemory(lpCallParams, dwSizeOfCallParams);
// Set the call parameters.
lpCallParams->dwTotalSize = dwSizeOfCallParams;
lpCallParams->dwBearerMode = LINEBEARERMODE_VOICE;
lpCallParams->dwMediaMode = LINEMEDIAMODE_DATAMODEM ;
lpCallParams->dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
lpCallParams->dwAddressMode = LINEADDRESSMODE_ADDRESSID;
lpCallParams->dwAddressID = g_dwCurrentLineAddr;
lpCallParams->dwDisplayableAddressSize =
lpTransOutput->dwDisplayableStringSize;
lpCallParams->dwDisplayableAddressOffset = sizeof (LINECALLPARAMS);
// Save the translated phone number for dialing.
lstrcpy (szDialablePhoneNum,
(LPTSTR) ((LPBYTE) lpTransOutput +
lpTransOutput->dwDialableStringOffset));
memcpy((LPBYTE) lpCallParams + lpCallParams->dwDisplayableAddressOffset,
(LPBYTE) lpTransOutput + lpTransOutput->dwDisplayableStringOffset,
lpTransOutput->dwDisplayableStringSize);
// Make the phone call. lpCallParams should be NULL if the default
// call setup parameters are requested.
g_MakeCallRequestID = lineMakeCall (g_CurrentLineInfo.hLine,
&g_hCall,
szDialablePhoneNum,
0,
NULL); // NULL for default voice call
/**************************/
// lpCallParams);
plz suggest if i need to change anything but as the call is successfully connected when only media mode is not set i guess problem is not with the memory location or anything but lies with the provider not sure ...............
or better maybe if u can suggest how i can do settings on my pocket pc for data calls
If you can't make a Data Modem type call, but you can make a voice call - Then are you sure you have Data Enabled on your Sim.
I'm sure I had that un-reachable error ages ago and it was due to not having Data Enabled. You have to contact your Sim provider to do that.
I have never included the lineTranslateAddress, i just put it in the way the user entered it( with a little error checking). If it works for voice though it must be OK.
With the sim, I have done this using 3 different sims and never had to set anything special on it. I could be lucky I guess and had sims already enabled. I doubt it though because one is 7 years old pre paid and not had any change since purchase. The second in a new pre paid and the 3rd is a full gprs enabled(not that gprs has anything to do with this). There should not be anything in the os to set either as when you do what you have done it is doing the "setup" just programatically.
I remember reading somewhere that the network had to support it but I can't be more specific.
What is your network? What is your device? what is your os?
When you say the voice call is connected what do you mean?..
1)your program at the other end answered.
2)the phone app on the other end answered.
3)your dialing end app received the connected message.
4)the returned value from linmakecall was > (-1).
5)some phone hardware on a real phone answered.
6) (my favourite way) the monitor next to your phone started buzzing, proving something was going on. Thats how I test my gprs connectivity :lol:

GPRS troubles with lineOpen on Magician

For MortRing, I use the common code to enable a line callback:
Code:
if ( lineInitialize( &LineApp, theApp.m_hInstance, LineCallback, theApp.m_pszAppName, &LineHandleCount ) == 0 )
{
LineHandles = new HLINE[LineHandleCount];
for(DWORD i = 0; i < LineHandleCount; i++)
{
if ( lineNegotiateAPIVersion( LineApp, i, 0x00010000, 0x00020000, &ver, &extensionID ) == 0 )
{
rc = lineOpen( LineApp, i, &LineHandles[i], ver, 0, (DWORD)this, LINECALLPRIVILEGE_MONITOR|LINECALLPRIVILEGE_OWNER, LINEMEDIAMODE_INTERACTIVEVOICE, NULL);
if ( rc < 0 )
LineHandles[i] = NULL;
}
}
}
Strangely, this leads to troubles with the Magician: You can connect and disconnect a GPRS connection once, but the second try will be aborted ("Connection cannot be established" or s.th. like that...).
There's nothing wrong in the callback function - I even tried it with an empty dummy, and the problem still remained.
Once the line handle were freed (i.e. program closed + restarted) everything works fine again - for the next GPRS connection...
So, any idea what's going wrong? Anybody with the same problem?
Some more information...
Closing and re-opening the line handles (and lineShutdown/Initialize - don't know if it's necessary) between the connections seems to help.
Also, I traced the callbacks, and found that the only difference between the working and the next (failing) connection is an addional LINECALLSTATE_PROCEEDING (between "dialing" and "connected") for the failing connection.
Could you please send this to the iMATE dev team since they have the same problems with their own ROMs ! ;o)

Switch for cprog.exe

Does anyone know the switch for cprog.exe to get to the "Call History" or "Speed Dial" screen directly without having to start the dialer first?
Or can anyone help me reverse engineer the cprog.exe to find this switch?
Thanks!
To open the call log directly use the code
Code:
HWND hPhoneMainWnd=::FindWindow(_T("Dialog"),_T("Phone"));
if (!hPhoneMainWnd)
{
PROCESS_INFORMATION pi = {0};
DWORD dwRes = 0;
BOOL bret=CreateProcess(_T("\\Windows\\cprog.exe"), _T(""), NULL, NULL, NULL, 0, NULL, NULL, NULL, &pi);
if (!bret) dwRes=GetLastError();
Sleep(500);
hPhoneMainWnd=::FindWindow(_T("Dialog"),_T("Phone"));
}
if (hPhoneMainWnd)
{
::PostMessage(hPhoneMainWnd,WM_COMMAND,0x00002712 /*History button*/,0);
}
To open the speed dial change the ID value 0x00002712 to that of the speed dial (I dont now it right now, but it is easy to find it)
Enjoy :twisted:
Thanks very much mmalek!!!
It works fine under 2003 (SE) but unfortunately it doesn't work under WM 5.0 (Magneto). Does your code only work for the 2003 platform?
Thanks again!
For WM5, you have to find out correct resource IDs.
For cprog.exe, open tapres.dll in some resource editor and lookup IDs there.
buzz
How do you find out the correct ressource ID? When I open the tapres.dll of WM2003 and try to find the resource ID 0x00002712 mmalek used in his code, I can find it nowhere...
I open the DLL with PE Explorer... where exactly do I have to look for these ID's?
Thanks a lot guys!
@buzz_lightyear: Are you sure the correct resource IDs are inside tapres.dll? I dont know much about Windows programming and please correct me if I am wrong, but from my understanding inside tapres.dll are only the resource ID's of the "Menu" and not of the "Buttons" of the Dialer.
Please could anyone give me a hint to find a solution? I really need this!
Thanks
Hi, the IDs are in the tapres.dll, but this is not what I used.
The ID for the "Call History" button is 22303 or 571F Hex so you can also use this to send the WM_COMMAND massage. What I used to get the ID is the RemoteSpy++ i just spied on the cprog.exe messages and then clicked the button I need then the resource id is in the wParam of the message. you should succed using either method...
Enjoy ---- :twisted:
Hi!
Thanks a lot mmalek for your hint! But I am really wondering how you managed to make RemoteSpy++ work with a Magneto device! If I try to use RemoteSpy++ from EVC++ 4.0 I get always an error message. Unfortunately the RemoteSpy tool from Visual Studio 2005 Beta2 has still a bug and does not work either. So I have still no idea how to get the right Resource ID's to start directly the "Call History" and "Speed dial" screen.
(0x0000571F does not work on my Magneto devices (Wizard & WM5 2020))
So if anyone could provide me with the right Resource ID's for the "Call History" and "Speed dial" button for Magneto devices I would REALLY appreciate if he would post them
Cheers
mmalek said:
To open the call log directly use the code
Code:
HWND hPhoneMainWnd=::FindWindow(_T("Dialog"),_T("Phone"));
if (!hPhoneMainWnd)
{
PROCESS_INFORMATION pi = {0};
DWORD dwRes = 0;
BOOL bret=CreateProcess(_T("\\Windows\\cprog.exe"), _T(""), NULL, NULL, NULL, 0, NULL, NULL, NULL, &pi);
if (!bret) dwRes=GetLastError();
Sleep(500);
hPhoneMainWnd=::FindWindow(_T("Dialog"),_T("Phone"));
}
if (hPhoneMainWnd)
{
::PostMessage(hPhoneMainWnd,WM_COMMAND,0x00002712 /*History button*/,0);
}
To open the speed dial change the ID value 0x00002712 to that of the speed dial (I dont now it right now, but it is easy to find it)
Enjoy :twisted:
Click to expand...
Click to collapse
how to use this code?
Sorry to resurrect this thread, but did anyone get anywhere with this for WM5 / WM6? It would be *really* handy for today screen apps such as XMT or rlToday to be able to have a button that takes you to missed calls, and for this we need a command line switch for cprog or a .exe - we cannot put raw C in XMT / rlToday themes...
This would rock as an exe, especially if it worked for 2003, WM5 and WM6 - any takers?
You can use these .exe helpers:
ShowCalls.exe
ShowIncomingCalls.exe
ShowMissedCalls.exe
ShowOutgoingCalls.exe
Windows Mobile Phone edition based, are opensource GPL so you can use, and distribuite as you want.
These utilities can be found on the \Tools folder of XIAMultitheme binaries, or sources too
You can download XMT (Always download Snapshots!) from here:
Download XMT Binaries
Super Duper!
You rock stef!
evilc said:
Super Duper!
You rock stef!
Click to expand...
Click to collapse
Also XMT now support: File="missedcalls"

Win32 Mode Failure to set text in static control

I have a problem in setting controls in a Win32 application.
When I use SendMessage to set a text string in a static control I get error number 120 which translated means: "This function is only valid in Win32 mode."
Here's the background:
I'm using Visual Studio 2005, I've installed the Windows Mobile 5 SDK.
The project was created using the New Project Wizard, with the following settings:
Visual C++/Smart Device
Win32 Smart Device Project
Platform SDK is: Windows Mobile 5.0 Pocket PC SDK
Windows application
I've added a dialog template resource and can bring up a dialog based on that resource. It contains a static control that I can read the text from, but attempting to set the text gives me the above error.
The relevent code (within the WM_INITDIALOG message handler) is:
Code:
char buffer[100];
HWND hCtrl = ::GetDlgItem(hDlg, IDC_TITLE);
LRESULT result = ::SendMessage(hCtrl, WM_GETTEXT, (WPARAM)80, (LPARAM)buffer);
This works, I get the correct text (ie the text I have placed into the static control using the dialog template editor) copied into the buffer. What follows is:
Code:
buffer[0] = 'A'; // Just to set up a different string
result = ::SendMessage(hCtrl, WM_SETTEXT, (WPARAM)0, (LPARAM)buffer);
if (result == 0)
{
LPVOID lpMsgBuf;
DWORD error = ::GetLastError();
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, 0, (LPTSTR)&lpMsgBuf, 0, NULL);
::MessageBox(NULL, (LPCTSTR)lpMsgBuf, (LPCWSTR)"LError", MB_OK | MB_ICONINFORMATION);
::LocalFree(lpMsgBuf);
}
The attempt to set the changed text string fails (ie result == 0), and the last error is 120, which is translated to the error message above.
This works the same in both the Windows Mobile 5 emulator, and if I run it on my Atom.
What does this mean? How could it be anything other than Win32 mode?
Is there a function or something I have to call to put it into Win32 mode?
Or is it a project setting in VS2005 that I haven't been able to find?
I'd very much appreciate any help on this.
Peter
Hi Peter.
The only problem I can see in your code is that you are using char instead of WCHAR. Windows Mobile devices only use UNICODE for API calls.
I don't think it is causing the error, but it is strange that you manage to get the correct text out using it.
The only thing I can think of is using GetWindowText and SetWindowText APIs instead of sending the message directly.
Maybe this will solve your problem.
I also notice that you did not initialize the buffer. The string needs to be null terminated so try initializeing all the elements before putting your 'A' in.
I thought 120 was not supported on this system ERROR_CALL_NOT_IMPLEMENTED.
Guys,
Thanks very much for the suggestions.
As for not initializing the buffer, I think the WM_GETTEXT call does that, all I do with the buffer[0] = 'A' call is to modify a single character that now contains the text that was copied out from the control.
But I take your point about using WCHAR, I'll do that when I get a chance.
And I'll try the Get and SetWindowText calls.
Thanks again.
Ok, How about this then?
The buffer is initialized by the WM_GETTEXT message, and it is set to the correct value (ie the initial contents of the control).
Changing the first character works.
The WM_SETTEXT message fails (result == 0) and the translated error (120) as displayed in the message box is "This function is only valid in Win32 mode."
The SetWindowText also fails with the same last error.
Does anyone know what "Win32 mode" is? I have spent time searching the MSDN and googling it. I've seen some references to it as an error message, but I haven't found an explanation.
Thanks,
Peter
Code:
WCHAR buffer[100];
HWND hCtl = ::GetDlgItem(hDlg, IDC_TITLE);
LRESULT result = ::SendMessage(hCtl, WM_GETTEXT, (WPARAM)80, (LPARAM)buffer);
buffer[0] = WCHAR('A');
//BOOL textResult = ::SetWindowText(hCtl, (LPCWSTR)buffer);
result = ::SendMessage(hCtl, WM_SETTEXT, (WPARAM)0, (LPARAM)buffer);
if (result == 0)
{
WCHAR errorTitle[] = L"LastError";
LPVOID lpMsgBuf;
DWORD error = ::GetLastError();
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, 0, (LPTSTR)&lpMsgBuf, 0, NULL);
::MessageBox(NULL, (LPCTSTR)lpMsgBuf, (LPCWSTR)errorTitle, MB_OK | MB_ICONINFORMATION);
::LocalFree(lpMsgBuf);
}
Ok, there is no apparent reason why your code doesn't work. Like OdeeanRDeathshead said according to MSDN error 120 means 'This function is not supported on this system.', something you definitely should not be getting.
One question: is this code inside a class member function? I am asking because of the '::' in front of every API.
Try removing them and see what happens.
Also, no need to use WCHAR('A'), just write L'A' save your self some typing in the long run.
P.S. In my year and a half of programming for Windows Mobile I never heard of a 'Win32 mode' or a function not working because of it. The error may be elsewhere in your code, some problem with name-spaces perhaps?
Are you running this on an actual device or just the emulator?
Hi levenum,
Thanks for the reply. Where to start?
Firstly I tend to use the scope resolution operator wherever possible. In this case ::SendMessage (for example), is meant to be a clear message to the reader that these functions are not member functions of the class, but instead exist in the global namespace. I have tried removing them and there is no difference.
You also asked if the code was in a class member function. Well, yes. It is a static member function of a specialization of a generic dialog class. Both the about box dialog and this setup dialog specialize this generic dialog class. Each has their own static dialog message processing function.
The code is in the part that handles the WM_INITDIALOG message. This is where I would normally (ie in Win32 on good ol' PC type windows) initialize controls before the dialog box is displayed. I have shown the dialog message function, and it is almost identical to the one for the about box that is generated when you create a Win32 project in the wizard.
One other point is that the GetLastError call and the format call are exactly out of the MSDN. If you look up the FormatMessage function, there is example code to translate the error code returned by GetLastError. That's exactly what I have here, and the message it gives is about not being in Win32 mode. So now I'm curious, how do you arrive at the 'This function is not supported on this system' comment. I looked for error and 120, and the only thing I could find was something about ARM messages "improper line syntax; wrong use of local label".
By the way, the SetWindowText function (commented out) gives exactly the same error code. As you say, surely both of these are allowed on this system.
I also appreciate you comment about not having heard of a Win32 mode.
But you have got me wondering if I can simplify the problem further. I will try the initial small project you get generated from the wizard, and in the about box dialog message processing function I will try to set the text in one of the two static controls on the about box.
Thanks again,
Peter
Code:
// Message handler for the setup dalog.
INT_PTR CALLBACK
DialogSetup::DialogSetupDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
// Create a Done button and size it.
SHINITDLGINFO shidi;
shidi.dwMask = SHIDIM_FLAGS;
shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN | SHIDIF_EMPTYMENU;
shidi.hDlg = hDlg;
SHInitDialog(&shidi);
// Set up strings
//LRESULT result = ::SendDlgItemMessage(hDlg, IDC_TITLE, WM_SETTEXT, 0, (LPARAM)"Setup");
WCHAR buffer[100];
HWND hCtl = ::GetDlgItem(hDlg, IDC_TITLE);
LRESULT result = ::SendMessage(hCtl, WM_GETTEXT, (WPARAM)80, (LPARAM)buffer);
buffer[0] = WCHAR('A');
//BOOL textResult = ::SetWindowText(hCtl, (LPCWSTR)buffer);
result = ::SendMessage(hCtl, WM_SETTEXT, (WPARAM)0, (LPARAM)buffer);
if (result == 0)
{
WCHAR errorTitle[] = L"LastError";
LPVOID lpMsgBuf;
DWORD error = ::GetLastError();
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, 0, (LPTSTR)&lpMsgBuf, 0, NULL);
::MessageBox(NULL, (LPCTSTR)lpMsgBuf, (LPCWSTR)errorTitle, MB_OK | MB_ICONINFORMATION);
::LocalFree(lpMsgBuf);
}
}
return (INT_PTR)TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
}
break;
case WM_CLOSE:
EndDialog(hDlg, message);
return TRUE;
#ifdef _DEVICE_RESOLUTION_AWARE
case WM_SIZE:
{
DRA::RelayoutDialog
(
GetInstance(),
hDlg,
DRA::GetDisplayMode() != DRA::Portrait ? MAKEINTRESOURCE(IDD_SETUP_WIDE) : MAKEINTRESOURCE(IDD_SETUP)
);
}
break;
#endif
}
return (INT_PTR)FALSE;
}
Hi levenum,
Thanks for the reply. Where to start?
Firstly I tend to use the scope resolution operator wherever possible. In this case ::SendMessage (for example), is meant to be a clear message to the reader that these functions are not member functions of the class, but instead exist in the global namespace. I have tried removing them and there is no difference.
You also asked if the code was in a class member function. Well, yes. It is a static member function of a specialization of a generic dialog class. Both the about box dialog and this setup dialog specialize this generic dialog class. Each has their own static dialog message processing function.
The code is in the part that handles the WM_INITDIALOG message. This is where I would normally (ie in Win32 on good ol' PC type windows) initialize controls before the dialog box is displayed. I have shown the dialog message function, and it is almost identical to the one for the about box that is generated when you create a Win32 project in the wizard.
One other point is that the GetLastError call and the format call are exactly out of the MSDN. If you look up the FormatMessage function, there is example code to translate the error code returned by GetLastError. That's exactly what I have here, and the message it gives is about not being in Win32 mode. So now I'm curious, how do you arrive at the 'This function is not supported on this system' comment. I looked for error and 120, and the only thing I could find was something about ARM messages "improper line syntax; wrong use of local label".
By the way, the SetWindowText function (commented out) gives exactly the same error code. As you say, surely both of these are allowed on this system.
I also appreciate you comment about not having heard of a Win32 mode.
But you have got me wondering if I can simplify the problem further. I will try the initial small project you get generated from the wizard, and in the about box dialog message processing function I will try to set the text in one of the two static controls on the about box.
Thanks again,
Peter
Code:
// Message handler for the setup dalog.
INT_PTR CALLBACK
DialogSetup::DialogSetupDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
// Create a Done button and size it.
SHINITDLGINFO shidi;
shidi.dwMask = SHIDIM_FLAGS;
shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN | SHIDIF_EMPTYMENU;
shidi.hDlg = hDlg;
SHInitDialog(&shidi);
// Set up strings
//LRESULT result = ::SendDlgItemMessage(hDlg, IDC_TITLE, WM_SETTEXT, 0, (LPARAM)"Setup");
WCHAR buffer[100];
HWND hCtl = ::GetDlgItem(hDlg, IDC_TITLE);
LRESULT result = ::SendMessage(hCtl, WM_GETTEXT, (WPARAM)80, (LPARAM)buffer);
buffer[0] = WCHAR('A');
//BOOL textResult = ::SetWindowText(hCtl, (LPCWSTR)buffer);
result = ::SendMessage(hCtl, WM_SETTEXT, (WPARAM)0, (LPARAM)buffer);
if (result == 0)
{
WCHAR errorTitle[] = L"LastError";
LPVOID lpMsgBuf;
DWORD error = ::GetLastError();
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, 0, (LPTSTR)&lpMsgBuf, 0, NULL);
::MessageBox(NULL, (LPCTSTR)lpMsgBuf, (LPCWSTR)errorTitle, MB_OK | MB_ICONINFORMATION);
::LocalFree(lpMsgBuf);
}
}
return (INT_PTR)TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
}
break;
case WM_CLOSE:
EndDialog(hDlg, message);
return TRUE;
#ifdef _DEVICE_RESOLUTION_AWARE
case WM_SIZE:
{
DRA::RelayoutDialog
(
GetInstance(),
hDlg,
DRA::GetDisplayMode() != DRA::Portrait ? MAKEINTRESOURCE(IDD_SETUP_WIDE) : MAKEINTRESOURCE(IDD_SETUP)
);
}
break;
#endif
}
return (INT_PTR)FALSE;
}
That error message comes from the free evc compilers. In the tool "error lookup" and in the help, it gives that mesage to correspond to that number.
I have just tested everthing you did. My dialog also uses a class with static methods for its routine. I used your exact code in the initial dialog handler and experimented with the origional contents of the controll. I tested on 2002 2003 2005 devices and can't make it fail. The worst i can get to happen is if there is no text to start with, just a square character displays after the A.
the only thing different is that you say two dialogs use that routine, but I am guessing that you are not doing bothe at once at this time.
Guys, thanks again for anything you can give me.
Lets see, I don't have the situation where two dialogs are using the same function. They both use a different message handling function (different name).
As I said in my last post (sorry I seem to have posted it twice), I was going to simplify the example. I've done that and I get the same problem.
I created another project with the same settings I described above, called "TestSetText". I made a change in only one place. In the function called "About", the message handling function for the about box dialog, I have inserted my example code to get and set the text for one of the static controls called IDC_STATIC_2. I have made no other changes to the code. So the modified About function is as below, and I have commented the section I have added:
Code:
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
// Create a Done button and size it.
SHINITDLGINFO shidi;
shidi.dwMask = SHIDIM_FLAGS;
shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN | SHIDIF_EMPTYMENU;
shidi.hDlg = hDlg;
SHInitDialog(&shidi);
// Code to check setting text - only change
//LRESULT result = SendDlgItemMessage(hDlg, IDC_STATIC_2, WM_SETTEXT, 0, L"Example");
WCHAR buffer[100];
HWND hCtl = GetDlgItem(hDlg, IDC_STATIC_2);
LRESULT result = SendMessage(hCtl, WM_GETTEXT, (WPARAM)80, (LPARAM)buffer);
MessageBox(NULL, (LPCTSTR)buffer, (LPCWSTR)L"Text from control", MB_OK | MB_ICONINFORMATION);
// Modify the extracted text
buffer[0] = L'A';
//BOOL textResult = SetWindowText(hCtl, (LPCWSTR)buffer);
result = SendMessage(hCtl, WM_SETTEXT, (WPARAM)0, (LPARAM)buffer);
if (result == 0)
{
WCHAR errorTitle[] = L"LastError";
LPVOID lpMsgBuf;
DWORD error = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, 0, (LPTSTR)&lpMsgBuf, 0, NULL);
MessageBox(NULL, (LPCTSTR)lpMsgBuf, (LPCWSTR)errorTitle, MB_OK | MB_ICONINFORMATION);
LocalFree(lpMsgBuf);
}
// End of my change
}
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
case WM_CLOSE:
EndDialog(hDlg, message);
return TRUE;
#ifdef _DEVICE_RESOLUTION_AWARE
case WM_SIZE:
{
DRA::RelayoutDialog(
g_hInst,
hDlg,
DRA::GetDisplayMode() != DRA::Portrait ? MAKEINTRESOURCE(IDD_ABOUTBOX_WIDE) : MAKEINTRESOURCE(IDD_ABOUTBOX));
}
break;
#endif
}
return (INT_PTR)FALSE;
}
So now there are no double colons, no second dialog, no base class, nothing else to confuse the issue. When the app starts all I have to do is invoke the Help|About menu.
When the WM_GETTEXT message is complete, buffer contains exactly the text I would have expected "TestSetText Version 1.0", and this is what is displayed in the message box. So in principle the SendMessage function works and the control handle (hCtl) is correct. This leads me to suspect that all necessary controls are created by the time the WM_INITDIALOG message is processed, and SHOULD be a good place to modify the controls prior to displaying the dialog box.
Modifying the first character in the buffer (setting it to 'A') succeeds as I can see in the debugger.
The attempt to send the WM_SETTEXT message fails (ie result == 0) and GetLastError returns 120 again. The code as I have it there translates this to "This function is only valid in Win32 mode." And this is displayed in the next message box.
When you see the about box, the first character in the IDC_STATIC_2 control has not been changed.
I've also tried using the SetWindowText call which returns non zero (a failure), and the same thing happens (GetLastError returns 120).
One final comment is that if you look up in the MSDN the FormatMessage function, it gives you code (that I have copied) to translate the GetLastError into a string. This gives the Win32 mode message above.
On the other hand, I have found the 120 error in the section "System Errors - Numerical Order" and 120 is listed there as "This function is not valid on this platform." which both of you guys have mentioned.
Ok, two different error messages. The Win32 mode error I don't understand. The not valid error is much more understandable, but how could these functions not be valid?
If you have stayed with me this far then you have a lot of patience.
Thanks
Peter
perhaps you could work around this. Define a value to use as your own message like #define MY_SETUP_MESSAGE ...some value.
Then do nothing in the handler for WM_INITDIALOG except post your own setup message. Do all your normal stuff there. If that succeeds then take a closer look at the timing of WM_INITDIALOG, else there is something waky going on.
Hang on a second, you wrote:
I've also tried using the SetWindowText call which returns non zero (a failure), and the same thing happens (GetLastError returns 120).
Click to expand...
Click to collapse
Is that correct or is it a typo? According to MSDN non zero return for SetWindowText means success, not failure.
One thing you should try is calling SetLastError(0) before calling SetWindowText. Last error is no automatically reset in any way, so it is possible that error 120 is a result of a previous function. Although that still wouldn't account for not seeing the change text in the control.
In any case this is strange. I always initialize controls in WM_INITDIALOG handler and it never failed before.
Ah, you're right. Sorry, I screwed that up. I misread the MSDN there and did a GetLastError anyway, which returned 120.
SetWindowText returns a value of 1, which implies success, but it wasn't successful in the sense of setting the text, when you see the about box it is unchanged.
I also did a SetLastError to zero before the call, and did a GetLastError after it (even though the return code said success), and it was zero. So by all accounts (return code and GetLastError) it should have worked but didn't. The about box is unchanged.
I have also SetLastError to zero before the SendMessage to set the text. That returns zero, and I am sure that the MSDN says should be TRUE if the text is set, so an error. Trouble is, GetLastError then gives zero implying that there was no failure. When you see the about box, the text is not changed so it did fail.
I will have to experiment some more. Maybe I can't set text in a static for some reason. Do I need to call InitCommonControls for that or something (which I haven't done)?
I will also have to try setting text in an edit control.
I used the format message and got the same win32 mode stuff now. However, the text was modified to the new value. I think the win32 mode error message is a bug. Put the same code into the emulator and the error returned is invalid handle. At least invalid handle is something more definite. In both cases, emulator and real device, even though the returned value is 0 for WM_SETTEXT, and the error message is there, I do not think there is an error. Have you just tried it without any error checking?
Are you creating the dialog using creatdialog/dialogbox?
Hi OdeeanRDeathshead, thanks for the reply.
I don't think the invalid handle error is right here because I have used the same control window handle (hCtl) a couple of statements before to retrieve the text and that worked. I guess what I haven't checked is whether the control window handle is changed somehow as a result of the first call, but that would be really weird.
You said that even though SendMessage/WM_SETTEXT returned 0, you thought it probably wasn't an error. Well, there is support for that in that when I SetLastError to zero just prior to calling it, and call GetLastError just after, the error code was zero, thus no error. But the reason I think that there WAS an error is that it did not modify the static control. This is what I get if I effectively don't do any error checking.
As for how I am creating the dialog, the only code I have modified from the original project created from the application wizard is in the WM_INITDIALOG section of the About function that I showed you above. The dialog is created in the WndProc message handling function for the main window, part of which is below. If it is the IDM_HELP_ABOUT command, from the menu, it calls DialogBox specifying the dialog message processing function 'About' where my modified code is.
The code below is produced by the application wizard.
Code:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
static SHACTIVATEINFO s_sai;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
[b]case IDM_HELP_ABOUT:
DialogBox(g_hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, About);
break;[/b]
case IDM_OK:
SendMessage (hWnd, WM_CLOSE, 0, 0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
etc
I think I am going to have to experiment some more on the weekend. Try some other controls etc.
By the way I meant to mention that exactly the same thing happens in both the emulator as well as my Atom. So far, in all of the combinations of code, I have not been able to programmatically change the text content of a static control on a dialog.
And I've just noticed that my attempt to highlight (bold) the relevent part of the code above didn't work.
D'oh!
Actually I have just thought of something that may be relevent.
The emulator and SDK that came by default with VisualStudio2005 is WindowsCE 2003. When I first tried my code in the emulator, it worked. I could not only set text in a static control, I was also successfully manipulating a date/time picker in a separate dialog. I did lots of GDI rendering in the main window as well. And this code also worked on a friend's WindowsCE2003 PDA.
Things looked good until I tried it on my Atom which is WindowsMobile 5.
None of the above worked (except the GDI rendering). I thought it may have been a problem with the development environment. So I downloaded the WindowsMobile 5 SDK which includes a WM5 emulator. I thought this is bound to fix the problem, ie generate the code with the WM5 SDK.
All of my problems above are with WM5 project and emulator. And I said I was using this way back in the first post.
OdeeanRDeathshead, I had a quick look at your profile and you seem to have some earlier XDA machines. Are you using Windows Mobile 5?
If the problem does turn out to be Windows Mobile 5 related, then that says something very bad about backwards compatibility for that platform. Could it also be a WM5 bug? Surely not something so fundamental as this?
I use evc++3 for a compiler, mainly because I am the kind of person who thinks - if its not broaken why change. I have an Atom and do use it to run code on. I have all os, ie 2002,2002pe,2003,2003se,2005, so I don't think this problem is with the device. It may be vis studio 2005, but others have said it works OK.
PPC operating systems have a nasty history of backwards compatibility issues. I could not say that this is the issue here, but it is definately one reason I stick to a lowest common denominator approach. Why not just get evc3 or evc4 and give them a try. They are free.
I guess I was hoping to do it with Visual Studio 2005 because that is what I use at work. These days I mainly program in C#/.NET.
I kind of miss the low level stuff that I used to do on windows a long time ago. But I reminisce.
I'm assuming that evc++ is embedded visual c++? It sounds like really good advice, I'll look for it and it sounds like it will fix all my problems. Especially if as you say, it works for WindowsMobile 5. Can you tell me if you are supposed to use the WindowsMobile 5 SDK with it?
So OdeeanRDeathshead and levenum, thanks a lot for your help guys.
Peter

idea for a small application... any help?

Ok, when I'm in my office I have poor signal issues that drain my battery and miss calls. If I switch to Roaming Only in my phone settings, then everything is just peachy. Problem is, its a lot of menus to click through every single time I come in to my office (Start, settings, phone, services, roaming, get settings, roaming only).
And then when I'm leaving, I want to turn the romaing settings back to automatic, once again its a lot of clicking.
I would imagine it would not be too difficult to write an app that could toggle that setting. Then it could be one click, or someone could even map the app to a hardware button for the ultimate ease of use.
I'm sure there are others who can see how useful such an app would be. Many of us do something like this all the time.
So, what do you think? Anyone willing to help develop this?
Sounds like a do-able program that would be very useful even for people not in your situation. Of course, I don't know how to, I'm just endorsing this idea.
In for this
GREAT!
Now, who can actually help figuring out how to code this? Can that sort of data even be accessed from standard APIs?
MortScript
Ok folks, until I have the time to find out what actually goes on behind the scenes when roaming settings are changed, I think our best bet is to write a script of keypresses/mouseclicks using mortscript.
Mortscript, in case you didn't know, is a simple batch process program, which lets you assign a series of commands to a script, sort of like a macro.
This will essentially be a script to go through the menus and click through options to do what we would do by hand. It will speed things up a bit, but it won't be as simple as a standalone app.
playing with mortscript now, I'll keep you guys posted.
EDIT: Anyone who wants to take a crack at this as well, by all means, mortscript is free! I'm just learning how to use it now, but if anyone has any experience with it, hit me up with suggestions! Or better yet, write a script and show me how it works!
Can anyone tell me what registry changes are made when you switch from roaming to automatic?
I can't seem to compare registry backups taken with PHM RegEdit (some propietary format, and no export to text option!)
Mortscript to the rescue....
This is still not the most ideal solution, but it works for me.
I wrote two Mortscript scripts that simulate the key taps automatically. The downside to this is that you can't toggle it on/off, you need to run one program to force roam, and another one to put it back to automatic.
USE THESE AT YOUR OWN RISK!
If you have any bugs/questions/comments, let me know.
Requirements
MortScript:
You need to install the mortscript interpreter first.
http://www.sto-helit.de/downloads/mortscript/MortScript-4.0.zip
The zip file attached below contains two .mscr files:
Roam
Roam-NO
Pretty self explanatory what does what. You can rename them if you want, this just works for me.
Dishe said:
I wrote two Mortscript scripts that simulate the key taps automatically. The downside to this is that you can't toggle it on/off, you need to run one program to force roam, and another one to put it back to automatic.
Click to expand...
Click to collapse
If you wanted to, you could write a temp file or reg key to check if the setting is on or off. In fact, the file wouldn't even need any data in it, you could just check for it's existence. That way you only need one script. Hope that helps you out.
I havent been able to find (or pull) the ril.dll file from a Mogul Wm6 installation, but once you have that file, you should be able to dump the exports and use the RIL_* functions by ordinal. This has been done on GSM phones.
I haven't had time yet, but I believe someone has dumped the files from the newest update rom.
Dishe,
I took your script and applied my suggestion to it. I also wrapped it up in a standalone package, so if anyone else wants to run it, they won't need MortScript installed as the exe is in here. If you already have MortScript installed, you can just run the .mscr file instead of the .exe of the same name.
What it will do is run the prog, then check for the existence of the file "roam" in the script path. If it's not there, it will run your roam function and then create the file. If it already exists (meaning you turned on roaming only), then it run your function to turn off roaming and delete the temp file. Hope it helps you out.
EDIT: If for some reason the key presses do the wrong thing, you can just set your phone back to automatic and delete the "roam" file in the script path if it's there, then you're back in business.
EDIT2: Added a longer wait time (5 secs) for the Comm Manager, should allow it to work with more graphic intensive Comm Managers (like the Kaiser 10-button, tested).
Vinny75 said:
I havent been able to find (or pull) the ril.dll file from a Mogul Wm6 installation, but once you have that file, you should be able to dump the exports and use the RIL_* functions by ordinal. This has been done on GSM phones.
I haven't had time yet, but I believe someone has dumped the files from the newest update rom.
Click to expand...
Click to collapse
I know, qouting myself, but.. you don't need the ordinal, you can get the function by name from the dll, so far I am able to use RIL_Initialize and RIL_GetRoamingMode to call my pfResultCallback, but the value I am getting in reutrn isn't making sense, so have to figure that out. I am using a modified tstril util. I can post the changes if anyone wants to take a look.
Got the following for RIL_GetRoaming Mode
Mode Value
Sprint Only 0x00000001
Automatic 0x000000FF
Roaming Only 0x000000FE
Now using RIL_SetRoamingMode, I can set the Sprint Only mode, the other two throw a 0x80004005 HRESULT, I can use 0x00000002 and 0x0000003 (constants defined if you search the internet), and they don't throw an error, but they dont actually change any settings...
You can get tstril from here:
http://wiki.xda-developers.com/index.php?pagename=RIL
Expanded ril.h (not sure how accurate):
http://www.xs4all.nl/~itsme/projects/xda/ril/ril.h
Replace the DoRIL function in tstril.cpp with this code to test:
Code:
typedef HRESULT (*pfnRIL_Initialize)(DWORD, RILRESULTCALLBACK, RILNOTIFYCALLBACK, DWORD, DWORD, HRIL*);
typedef HRESULT (*pfnRIL_GetRoamingMode)(HRIL);
typedef HRESULT (*pfnRIL_SetRoamingMode)(HRIL, DWORD);
//HRIL g_hRIL;
HINSTANCE g_hDLL;
HRESULT g_hResult;
DWORD
DoRIL(LPVOID lpvoid)
{
HRESULT result;
DWORD dwNotificationClasses = 0xFF0000;
LRESULT lresult;
TCHAR szString[256];
SendMessage(g_hwndEdit, LB_RESETCONTENT, 0, 0);
lresult = SendMessage(g_hwndEdit, LB_GETHORIZONTALEXTENT, 0, 0);
SendMessage(g_hwndEdit, LB_SETHORIZONTALEXTENT, 1000, 0);
//result = RIL_Initialize(1, ResultCallback, NotifyCallback,
// dwNotificationClasses, g_dwParam, &g_hRil);
//wsprintf(szString, L"RIL Handle: %08X, result %08X", g_hRil, result);
//SendMessage(g_hwndEdit, LB_ADDSTRING, 0, (LPARAM) szString);
g_hRil = NULL;
g_hDLL = LoadLibrary(L"ril.dll");
//HRESULT hResult = 0;
if (g_hDLL != NULL)
{
pfnRIL_Initialize lpfnRIL_Initialize = (pfnRIL_Initialize)GetProcAddress(g_hDLL, L"RIL_Initialize");
if (lpfnRIL_Initialize)
{
result = (lpfnRIL_Initialize)(1, ResultCallback, NULL /*NotifyCallback*/, 0 /*dwNotificationClasses*/, 0 /*g_dwParam*/, &g_hRil);
if (result == S_OK)
{
wsprintf(szString, L"Initialize RIL Handle: %08X, result %08X", g_hRil, result);
SendMessage(g_hwndEdit, LB_ADDSTRING, 0, (LPARAM) szString);
pfnRIL_GetRoamingMode lpfnRIL_GetRoamingMode = (pfnRIL_GetRoamingMode)GetProcAddress(g_hDLL, L"RIL_GetRoamingMode");
if (lpfnRIL_GetRoamingMode)
{
g_hResult = (lpfnRIL_GetRoamingMode)(g_hRil);
wsprintf(szString, L"GetRoamingMode RIL Handle: %08X, g_hResult %08X", g_hRil, g_hResult);
SendMessage(g_hwndEdit, LB_ADDSTRING, 0, (LPARAM) szString);
}
//pfnRIL_SetRoamingMode lpfnRIL_SetRoamingMode = (pfnRIL_SetRoamingMode)GetProcAddress(g_hDLL, L"RIL_SetRoamingMode");
//if (lpfnRIL_SetRoamingMode)
//{
// g_hResult = (lpfnRIL_SetRoamingMode)(g_hRil, 254);
// wsprintf(szString, L"SetRoamingMode RIL Handle: %08X, g_hResult %08X", g_hRil, g_hResult);
// SendMessage(g_hwndEdit, LB_ADDSTRING, 0, (LPARAM) szString);
//}
}
}
//FreeLibrary(g_hDLL);
}
// while(1) {
// Sleep(100);
//// wsprintf(szString, L"%s",L"...");
//// SendMessage(g_hwndEdit, LB_ADDSTRING, 0, (LPARAM) szString);
// }
return 0;
}
Thanks for the work on those Mort Scripts!
Thank you!
wow, I haven't checked this thread in a while...
Vinny75, I haven't had time to play with this, but it looks like you've been making some progress... how far have you gotten with this?
The following values you should work for the second parameter of the RIL_GetRoamingMode and RIL_SetRoamingMode functions... they appeared to work on my phone
Mode RIL_GetRoamingMode RIL_SetRoamingMode
Sprint Only 0x00000001 0x00000001
Automatic 0x000000FF 0x00000004
Roaming Only 0x000000FE 0x00000005
I found the RIL_SetRoamingMode value in the following Registry Key
[HKEY_LOCAL_MACHINE\SOFTWARE\OEM\PhoneSetting\NetworkService]
Vinny75 said:
The following values you should work for the second parameter of the RIL_GetRoamingMode and RIL_SetRoamingMode functions... they appeared to work on my phone
Mode RIL_GetRoamingMode RIL_SetRoamingMode
Sprint Only 0x00000001 0x00000001
Automatic 0x000000FF 0x00000004
Roaming Only 0x000000FE 0x00000005
I found the RIL_SetRoamingMode value in the following Registry Key
[HKEY_LOCAL_MACHINE\SOFTWARE\OEM\PhoneSetting\NetworkService]
Click to expand...
Click to collapse
So would editing the registry be sufficient to change the roaming mode of the phone?
Did you compile an app to do this?
slightly off topic, but i think vinny75 might know the answer. id like to modify my alltel-based rom to give sprint only, automatic, roaming only options (alltel gives home only and automatic.) is ril.dll all that is needed from the sprint rom?
Dishe said:
So would editing the registry be sufficient to change the roaming mode of the phone?
Did you compile an app to do this?
Click to expand...
Click to collapse
I just compiled a quick and dirty app to test the values... the source is in my previous posts

Categories

Resources