|
Yes, according to the C99 standard: "The void type comprises an empty set of values; it is an incomplete type that cannot be
completed."
Applying sizeof to an incomplete type is an error.
|
|
|
|
|
With FindWindow and FindChildWindows API functions, I got the handle of SysListView32 control of mmsys.cpl panel. When I was trying to search the text of each entries on the ListCtrl, it always crashed.
My code snippet is as the below.
void CMainDlg::OnBnClickedGetDolby()
{
KillRunningApplet(_T("Sound"));
if(!LaunchCplApplet(_T("mmsys.cpl"), 0, 0)) {
OutputDebugString(_T("LaunchCplApplet fails. \n"));
return;
}
CWnd* pWnd = NULL;
int i = 0;
while(!pWnd) {
pWnd = FindWindow(NULL, _T("Sound"));
if(pWnd) {
OutputDebugString(_T("Found Sound window. \n"));
break;
}
Sleep(10);
i++;
if(i > 1000) {
OutputDebugString(_T("Sound window is not found. \n"));
return;
}
}
m_hListView = NULL;
for(i = 0; i < 2; i++) {
EnumChildWindows(pWnd->m_hWnd, DoSomethingHelper, (LPARAM)this);
if(m_hListView) {
OutputDebugString(_T("Got SysListView32"));
break;
}
else {
OutputDebugString(_T("SysListView32 is not found."));
if(i == 1) {
return;
}
}
}
CListView* pView = (CListView*)FromHandle(m_hListView);
CListCtrl& Ctrl = pView->GetListCtrl();
LVFINDINFO info = {0};
int iIndex = 0;
info.flags = LVFI_PARTIAL | LVFI_STRING;
info.psz = _T("Speaker\0");
if((iIndex = Ctrl.FindItem(&info)) != -1) {
OutputDebugString(_T("Speaker-like entry is found."));
}
}
BOOL CALLBACK DoSomethingHelper(HWND hwnd, LPARAM lParam)
{
TCHAR sClassName[MAX_PATH] = {0};
GetClassName(hwnd, sClassName, MAX_PATH);
if(wcscmp(sClassName, _T("SysListView32")) == 0) {
CMainDlg* pMain = (CMainDlg*)lParam;
pMain->m_hListView = hwnd;
}
OutputDebugString(sClassName);
return TRUE;
}
Maxwell Chen
|
|
|
|
|
Which applicaion crashes? the applet or your application?
|
|
|
|
|
A dialog box popped up saying "Windows Shell Common DLL has stopped working". When I clicked [Close program] of that popup, the applet was gone but my application still was alive.
I traced into the source of MFC. The problem is the m_hWnd of that CListCtrl.
_AFXCMN_INLINE int CListCtrl::FindItem(LVFINDINFO* pFindInfo, int nStart) const
{ ASSERT(::IsWindow(m_hWnd)); return (int) ::SendMessage(m_hWnd, LVM_FINDITEM, nStart, (LPARAM)pFindInfo); }
Maxwell Chen
modified on Friday, September 25, 2009 2:09 AM
|
|
|
|
|
hmm..
This is because you are passing a string pointer to another process. And when the other process try to access that pointer, exception occurs. You have to allocate the memoy in the target process( VirtualAllocEx() ), copy the string to that process' memory( WriteProcessMemory()). Then set that pointer in the LVM_FINDITEM structure and call FindItem().
|
|
|
|
|
I did this as the below, but pBuffer is bad_ptr and WriteProcessMemory returns fail.
LVFINDINFO info = {0};
int iIndex = 0;
TCHAR sTxt[MAX_PATH] = {0};
SIZE_T nByte = 0;
wcscpy(sTxt, _T("Speaker"));
info.flags = LVFI_PARTIAL | LVFI_STRING;
TCHAR* pBuffer = (TCHAR*)::VirtualAllocEx(m_hCplProcess, NULL, MAX_PATH, MEM_RESERVE, PAGE_READWRITE);
if(!WriteProcessMemory(m_hCplProcess, pBuffer, sTxt, MAX_PATH, &nByte)) {
return;
}
info.psz = pBuffer;
if((iIndex = Ctrl.FindItem(&info)) != -1) {
OutputDebugString(_T("Speaker-like entry is found."));
}
VirtualFreeEx(m_hCplProcess, pBuffer, MAX_PATH, MEM_RELEASE);
Maxwell Chen
|
|
|
|
|
Maxwell Chen wrote: TCHAR* pBuffer = (TCHAR*)::VirtualAllocEx(m_hCplProcess, NULL, MAX_PATH, MEM_RESERVE, PAGE_READWRITE);
You have to pass flAllocationType as MEM_COMMIT|MEM_RESERVE
|
|
|
|
|
Naveen wrote: You have to pass flAllocationType as MEM_COMMIT|MEM_RESERVE
I did, too. And it crashed as well ...
TCHAR* pBuffer = NULL;
pBuffer = (TCHAR*)::VirtualAllocEx(m_hCplProcess, NULL, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if(!pBuffer) {
return;
}
I also tried to VirtualAllocEx a LVFINDINFO object to replace the local one. It crashed too but at different line. Not at FindItem call but at the line
LVFINDINFO* pInfo = NULL;
pInfo->flags = LVFI_PARTIAL | LVFI_STRING;
Maxwell Chen
|
|
|
|
|
Maxwell Chen wrote: I also tried to VirtualAllocEx a LVFINDINFO object to replace the local one. It crashed too but at different line. Not at FindItem call but at the line
hmm..I missed that one...
here is the correct step..
1 . VirtualAlloc string in the remote process
2. write the string to that memory.
3. create local object of LVFINDINFO.
4. Set the flags and psz as the memory of the remote process
5. Allocate another memory in the remote process, who's size = sizeof( LVFINDINFO).
6. copy the content of the local LVFINDINFO structure to the remote memory using writeprocessmemory
7. Pass the pointer of the remote LVFINDINFO to the finditem() function
|
|
|
|
|
Naveen wrote: 3. create local object of LVFINDINFO.
4. Set the flags and psz as the memory of the remote process
5. Allocate another memory in the remote process, who's size = sizeof( LVFINDINFO).
Thank you very much. It does not crash now.
Maxwell Chen
|
|
|
|
|
I'm using VC++2005. Make a project SDI which derived from CListView. Say it is CMyListView, then add OnMouseMove, OnLbuttondown, OnLbuttonup process to CMyListView.
void CMyListView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if(nFlags & MK_LBUTTON)
{
AfxMessageBox(_T("enter"));
}
CListView::OnMouseMove(nFlags, point);
}
void CMyListView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
SetCapture();
CListView::OnLButtonDown(nFlags, point);
}
void CMyListView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
ReleaseCapture();
CListView::OnLButtonUp(nFlags, point);
}
Then compile the project, drag and push mouse button in the view. No message box will pop up. But if it is a common CView, the message box will pop up. What's going on?
One day a pretty girl asked me:"Do u think you are handsome?" "I don't think so!".She gave a slap in my face:"Why lying?"...
|
|
|
|
|
well am facing same problem
|
|
|
|
|
Hi,
I need to call telnet commands (login, do somthing, logout) inside my C/C++ code. How do I do it?
Best,
Jun
|
|
|
|
|
You can do this using socket programming.
Connect to the telnet server using the IP address of the telnet server and the telnet port (Usually 23).
Now send the telnet commands and receive responses on this socket.
«_Superman_»
I love work. It gives me something to do between weekends.
|
|
|
|
|
Hello All,
How can I copy a multidimensional array? For example an array such as this one:
CListViewCell (*m_pCell)[50] = new CListViewCell[cpy.m_nRows][50];
Sorry it's been years, but I don't think this will work:
memcpy(m_pCell, cpy.m_pCell, sizeof(cpy.m_pCell));
The code is in an assignment function (operator=) of a class. Values have been changed to keep it simple.
Any help would be appreciated!
Paul
modified on Thursday, September 24, 2009 9:47 PM
|
|
|
|
|
|
Hi,
I just had a Thread (discussion) with David Crow for Which I made an assumption
which maybe somebody can confirm or refute
when allocating an object with the new operator
storage is allocated from the PROCESS heap
The thing that makes me unsure about this is that COBject which is a dervived class
for a lot of MFC objects has a new operator
to summerize
storage in fuction is stack storage which is gone when you leave the function
for thread storage -- use Thread Local storage
new is Process storage
I would appreciate your comments
|
|
|
|
|
First will you stop using hard returns please? The lines will wrap automatically according to the screen resolution if you hadn't known that.
Second, your query is completely unclear.
It is a crappy thing, but it's life -^ Carlo Pallini
|
|
|
|
|
Actually itz a poem, sir.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Generally, dynamic memory allocation is done on the heap.
This may be done using the new operator , malloc , GlobalAlloc etc.
I do not understand the rest of your question.
«_Superman_»
I love work. It gives me something to do between weekends.
|
|
|
|
|
I just assumed that if I created a Object with the new operator it would be around for lifetime of the app/CWinapp
|
|
|
|
|
Do you mean create an object of a class derived from CObject using the new operator ?
Yes, it will be available for the lifetime of the application.
The pointer tracking this object must be made available to all functions using this object.
For example, create a CDialog pointer as a member of your class.
In the constructor of your class create the CDialog object using new .
Now in any methods of your class you can access the CDialog object using the CDialog pointer.
class A
{
CDialog* m_pDlg;
public:
A()
{
m_pDlg = new CDialog(IDD_MYDLG);
m_pDlg->Create(IDD_MYDLG);
}
~A()
{
delete m_pDlg;
}
void One()
{
}
void Two()
{
}
};
«_Superman_»
I love work. It gives me something to do between weekends.
|
|
|
|
|
not only Class A but any other Classes in the App as long as I save the Pointer
thnakx again
|
|
|
|
|
Sure, as long as the pointer is accessible to the other classes.
«_Superman_»
I love work. It gives me something to do between weekends.
|
|
|
|
|