|
i am calling that dialogbox from windows7 login screen by clicking one tile image .then it displays .but if i click out side the dialog then it goes to back.i don't want that please help me i past code
HRESULT PasswordResetCredential::SetSelected(BOOL* pbAutoLogon)
{
*pbAutoLogon = FALSE;
//Ilantus
fetchPortalURL((WCHAR)"");
return S_FALSE;
}
void fetchPortalURL(WCHAR username) {
DialogBox((HINSTANCE)g_hinst, MAKEINTRESOURCE(IDD_DIALOG1),NULL, InputBox_WndProc);
}
|
|
|
|
|
The third parameter which is the parent is given as NULL.
Set the parent to the desired window to make it modal.
|
|
|
|
|
hi,
santosh thanks for reply .how to do that.please guide me.
|
|
|
|
|
santosh
i set that parent windo it is not working.
thanks
venkatesh
|
|
|
|
|
|
hi ,
please check this code;
Thanks
venkatesh
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) 2012 Ilantus Technologies Pvt. Ltd.. All rights reserved.
//
//
#ifndef WIN32_NO_STATUS
#include <ntstatus.h>
#define WIN32_NO_STATUS
#endif
#include <tchar.h>
#include "PasswordResetCredential.h"
#include "guid.h"
#include "resource.h"
// Added by Suren & Gopi
#include <windows.h>
#include <winreg.h>
#include <stdio.h>
#include <exdisp.h>
#include "ax.h"
extern HINSTANCE hInstance;
typedef int (WINAPI * PFRUNGATEFRAMEWORKPWDRESET) (HWND, PWSTR, PWSTR, PWSTR);
// PasswordResetCredential ////////////////////////////////////////////////////////
//venkat
//HMODULE hInst;
char IB_res[10];
double defaultValue = 0;
HWND hwebf;
bool loaded, has_clicked, isquit=false;
INT_PTR CALLBACK InputBox_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_INITDIALOG:
{
char url[1024] = {0};//venkat come
HKEY keyHandle = 0;
DWORD size = sizeof(url);
DWORD type=0;
/////////
ShowWindow(hwnd,SW_SHOWMAXIMIZED);
HWND hk = GetDlgItem(hwnd,IDC_CUSTOM1);
RECT rc = {0};
GetClientRect(hwnd,&rc);
SetWindowPos(hk,0,0,0,rc.right,rc.bottom,SWP_SHOWWINDOW);
//HINSTANCE hInstance1;
// HICON hIcon;
//hIcon =(HICON)LoadImage( hInstance1,
// MAKEINTRESOURCE(IDI_ICON1),
// IMAGE_ICON,
// GetSystemMetrics(SM_CXSMICON),
// GetSystemMetrics(SM_CYSMICON),
// 0);
// if(hIcon)
// {
// SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
// }
/////////
HWND hX = GetDlgItem(hwnd,IDC_CUSTOM1);
SendMessage(hX,AX_INPLACE,1,0);
LONG ret = RegOpenKey(HKEY_LOCAL_MACHINE,L"SOFTWARE\\Ilantus\\PMP", &keyHandle);
if(ret == ERROR_SUCCESS)
{
RegQueryValueEx( keyHandle, L"url", 0, &type, (BYTE*)url, &size);
}
RegCloseKey(keyHandle);
IWebBrowser2* wb = 0;
SendMessage(hX,AX_QUERYINTERFACE,(WPARAM)&IID_IWebBrowser2,(LPARAM)&wb);
if (wb)
{
wb->Navigate((BSTR)url,0,0,0,0);
wb->Release();
}
return TRUE;
}
//case WM_RBUTTONDBLCLK:
// {
// ShowWindow(hwnd,SW_SHOWMAXIMIZED);
// return TRUE;
// }
case WM_LBUTTONDBLCLK:
{
ShowWindow(hwnd,SW_SHOWMAXIMIZED);
return TRUE;
}
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
/* if (!GetDlgItemText(hwnd, IDC_EDIT, IB_res, 10))
*IB_res = 0;*/
case IDCANCEL:
EndDialog(hwnd, wParam);
break;
}
break;
default:
return FALSE;
}
return TRUE;
}
//HINSTANCE hInstance;
HWND hwndParent;
/////////venkat
PasswordResetCredential::PasswordResetCredential():
_cRef(1),
_pCredProvCredentialEvents(NULL)
{
DllAddRef();
ZeroMemory(_rgCredProvFieldDescriptors, sizeof(_rgCredProvFieldDescriptors));
ZeroMemory(_rgFieldStatePairs, sizeof(_rgFieldStatePairs));
ZeroMemory(_rgFieldStrings, sizeof(_rgFieldStrings));
}
PasswordResetCredential::~PasswordResetCredential()
{
for (int i = 0; i < ARRAYSIZE(_rgFieldStrings); i++)
{
CoTaskMemFree(_rgFieldStrings[i]);
CoTaskMemFree(_rgCredProvFieldDescriptors[i].pszLabel);
}
DllRelease();
}
// Initializes one credential with the field information passed in.
// Set the value of the SFI_FIMTITLE field to pwzUsername.
// Optionally takes a password for the SetSerialization case.
HRESULT PasswordResetCredential::Initialize(
const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR* rgcpfd,
const FIELD_STATE_PAIR* rgfsp,
PCWSTR pwzUsername,
PCWSTR pwzPassword
)
{
UNREFERENCED_PARAMETER(pwzPassword);
HRESULT hr = S_OK;
// Copy the field descriptors for each field. This is useful if you want to vary the
// field descriptors based on what Usage scenario the credential was created for.
for (DWORD i = 0; SUCCEEDED(hr) && i < ARRAYSIZE(_rgCredProvFieldDescriptors); i++)
{
_rgFieldStatePairs[i] = rgfsp[i];
hr = FieldDescriptorCopy(rgcpfd[i], &_rgCredProvFieldDescriptors[i]);
}
// Initialize the String values of all the fields.
if (SUCCEEDED(hr))
{
hr = SHStrDupW(L"Forgot Password", &_rgFieldStrings[SFI_FIMTITLE]);
}
if (SUCCEEDED(hr))
{
hr = SHStrDupW(pwzUsername ? pwzUsername : L"", &_rgFieldStrings[SFI_USERNAME]);
}
if (SUCCEEDED(hr))
{
hr = SHStrDupW(L"Submit", &_rgFieldStrings[SFI_SUBMIT_BUTTON]);
}
if (SUCCEEDED(hr))
{
hr = SHStrDupW(L"e.g. ilantususer", &_rgFieldStrings[SFI_SAMPLE]);
}
return S_OK;
}
// LogonUI calls this in order to give us a callback in case we need to notify it of anything.
HRESULT PasswordResetCredential::Advise(
ICredentialProviderCredentialEvents* pcpce
)
{
if (_pCredProvCredentialEvents != NULL)
{
_pCredProvCredentialEvents->Release();
}
_pCredProvCredentialEvents = pcpce;
_pCredProvCredentialEvents->AddRef();
return S_OK;
}
// LogonUI calls this to tell us to release the callback.
HRESULT PasswordResetCredential::UnAdvise()
{
if (_pCredProvCredentialEvents)
{
_pCredProvCredentialEvents->Release();
}
_pCredProvCredentialEvents = NULL;
return S_OK;
}
void fetchPortalURL(WCHAR username) {
//char url[1024] = {0};//venkat come
// HKEY keyHandle = 0;
//DWORD size = sizeof(url);
//DWORD type=0;
//
//LONG ret = RegOpenKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Ilantus\\PMP", &keyHandle);
//if(ret == ERROR_SUCCESS)
//{
// RegQueryValueEx( keyHandle, L"url", 0, &type, (BYTE*)url, &size);
//}
//RegCloseKey(keyHandle);
////venkat
//MessageBox(NULL,NULL,L"hi23",MB_SYSTEMMODAL|MB_ICONINFORMATION);
OleInitialize(0);
if (!AXRegister())
DialogBox((HINSTANCE)g_hinst, MAKEINTRESOURCE(IDD_DIALOG1),NULL, InputBox_WndProc);
////venkat
//MessageBox(NULL, (LPCWSTR)url, L"Ilantus PMP URL", MB_SYSTEMMODAL|MB_ICONINFORMATION);
//system(( " c:\\progra~1\\intern~1\\iexplore.exe www.google.co.in"));
//HINSTANCE hInstance = ShellExecute(NULL, L"open", (LPCWSTR)url, NULL, NULL, SW_MAXIMIZE);
}
// LogonUI calls this function when our tile is selected (zoomed).
// If you simply want fields to show/hide based on the selected state,
// there's no need to do anything here - you can set that up in the
// field definitions. But if you want to do something
// more complicated, like change the contents of a field when the tile is
// selected, you would do it here.
HRESULT PasswordResetCredential::SetSelected(BOOL* pbAutoLogon)
{
*pbAutoLogon = FALSE;
//Ilantus
fetchPortalURL((WCHAR)"");
return S_FALSE;
}
// Similarly to SetSelected, LogonUI calls this when your tile was selected
// and now no longer is. The most common thing to do here (which we do below)
// is to clear out the password field.
HRESULT PasswordResetCredential::SetDeselected()
{
HRESULT hr = S_OK;
if (_rgFieldStrings[SFI_USERNAME])
{
//CoTaskMemFree(_rgFieldStrings[SFI_USERNAME]);
hr = wcscpy_s(_rgFieldStrings[SFI_USERNAME], wcslen(L"") + 1, L"");
if (SUCCEEDED(hr) && _pCredProvCredentialEvents)
{
_pCredProvCredentialEvents->SetFieldString(this, SFI_USERNAME, _rgFieldStrings[SFI_USERNAME]);
}
}
return hr;
}
// Gets info for a particular field of a tile. Called by logonUI to get information to
// display the tile.
HRESULT PasswordResetCredential::GetFieldState(
DWORD dwFieldID,
CREDENTIAL_PROVIDER_FIELD_STATE* pcpfs,
CREDENTIAL_PROVIDER_FIELD_INTERACTIVE_STATE* pcpfis
)
{
HRESULT hr;
// Validate paramters.
if ((dwFieldID < ARRAYSIZE(_rgFieldStatePairs)) && pcpfs && pcpfis)
{
*pcpfs = _rgFieldStatePairs[dwFieldID].cpfs;
*pcpfis = _rgFieldStatePairs[dwFieldID].cpfis;
hr = S_OK;
}
else
{
hr = E_INVALIDARG;
}
return hr;
}
// Sets ppwsz to the string value of the field at the index dwFieldID.
HRESULT PasswordResetCredential::GetStringValue(
DWORD dwFieldID,
PWSTR* ppwsz
)
{
HRESULT hr;
// Check to make sure dwFieldID is a legitimate index.
if (dwFieldID < ARRAYSIZE(_rgCredProvFieldDescriptors) && ppwsz)
{
// Make a copy of the string and return that. The caller
// is responsible for freeing it.
hr = SHStrDupW(_rgFieldStrings[dwFieldID], ppwsz);
}
else
{
hr = E_INVALIDARG;
}
return hr;
}
// Gets the image to show in the user tile.
HRESULT PasswordResetCredential::GetBitmapValue(
DWORD dwFieldID,
HBITMAP* phbmp
)
{
HRESULT hr;
// Validate paramters.
if ((SFI_TILEIMAGE == dwFieldID) && phbmp)
{
HBITMAP hbmp = LoadBitmap(HINST_THISDLL, MAKEINTRESOURCE(IDB_TILE_IMAGE));
if (hbmp != NULL)
{
hr = S_OK;
*phbmp = hbmp;
}
else
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
else
{
hr = E_INVALIDARG;
}
return hr;
}
// Sets pdwAdjacentTo to the index of the field the submit button should be
// adjacent to. We recommend that the submit button is placed next to the last
// field which the user is required to enter information in. Optional fields
// should be below the submit button.
HRESULT PasswordResetCredential::GetSubmitButtonValue(
DWORD dwFieldID,
DWORD* pdwAdjacentTo
)
{
HRESULT hr;
// Validate parameters.
if ((SFI_SUBMIT_BUTTON == dwFieldID) && pdwAdjacentTo)
{
// pdwAdjacentTo is a pointer to the fieldID you want the submit
// button to appear next to.
*pdwAdjacentTo = SFI_USERNAME;
hr = S_OK;
}
else
{
hr = E_INVALIDARG;
}
return hr;
}
// Sets the value of a field which can accept a string as a value.
// This is called on each keystroke when a user types into an edit field.
HRESULT PasswordResetCredential::SetStringValue(
DWORD dwFieldID,
PCWSTR pwz
)
{
HRESULT hr;
// Validate parameters.
if (dwFieldID < ARRAYSIZE(_rgCredProvFieldDescriptors) &&
(CPFT_EDIT_TEXT == _rgCredProvFieldDescriptors[dwFieldID].cpft ||
CPFT_PASSWORD_TEXT == _rgCredProvFieldDescriptors[dwFieldID].cpft))
{
PWSTR* ppwszStored = &_rgFieldStrings[dwFieldID];
CoTaskMemFree(*ppwszStored);
hr = SHStrDupW(pwz, ppwszStored);
}
else
{
hr = E_INVALIDARG;
}
return hr;
}
//-------------
// The following methods are for logonUI to get the values of various UI elements and then communicate
// to the credential about what the user did in that field. However, these methods are not implemented
// because our tile doesn't contain these types of UI elements
HRESULT PasswordResetCredential::GetCheckboxValue(
DWORD dwFieldID,
BOOL* pbChecked,
PWSTR* ppwszLabel
)
{
UNREFERENCED_PARAMETER(dwFieldID);
UNREFERENCED_PARAMETER(pbChecked);
UNREFERENCED_PARAMETER(ppwszLabel);
return E_NOTIMPL;
}
HRESULT PasswordResetCredential::GetComboBoxValueCount(
DWORD dwFieldID,
DWORD* pcItems,
DWORD* pdwSelectedItem
)
{
UNREFERENCED_PARAMETER(dwFieldID);
UNREFERENCED_PARAMETER(pcItems);
UNREFERENCED_PARAMETER(pdwSelectedItem);
return E_NOTIMPL;
}
HRESULT PasswordResetCredential::GetComboBoxValueAt(
DWORD dwFieldID,
DWORD dwItem,
PWSTR* ppwszItem
)
{
UNREFERENCED_PARAMETER(dwFieldID);
UNREFERENCED_PARAMETER(dwItem);
UNREFERENCED_PARAMETER(ppwszItem);
return E_NOTIMPL;
}
HRESULT PasswordResetCredential::SetCheckboxValue(
DWORD dwFieldID,
BOOL bChecked
)
{
UNREFERENCED_PARAMETER(dwFieldID);
UNREFERENCED_PARAMETER(bChecked);
return E_NOTIMPL;
}
HRESULT PasswordResetCredential::SetComboBoxSelectedValue(
DWORD dwFieldId,
DWORD dwSelectedItem
)
{
UNREFERENCED_PARAMETER(dwFieldId);
UNREFERENCED_PARAMETER(dwSelectedItem);
return E_NOTIMPL;
}
HRESULT PasswordResetCredential::CommandLinkClicked(DWORD dwFieldID)
{
UNREFERENCED_PARAMETER(dwFieldID);
return E_NOTIMPL;
}
//------ end of methods for controls we don't have in our tile ----//
// Collect the username and password into a serialized credential for the correct usage scenario
// (logon/unlock is what's demonstrated in this sample). LogonUI then passes these credentials
// back to the system to log on.
HRESULT PasswordResetCredential::GetSerialization(
CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE* pcpgsr,
CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs,
PWSTR* ppwszOptionalStatusText,
CREDENTIAL_PROVIDER_STATUS_ICON* pcpsiOptionalStatusIcon
)
{
UNREFERENCED_PARAMETER(pcpgsr);
UNREFERENCED_PARAMETER(pcpcs);
UNREFERENCED_PARAMETER(ppwszOptionalStatusText);
UNREFERENCED_PARAMETER(pcpsiOptionalStatusIcon);
HWND phwndOwner = NULL;
HMODULE hGateFrameworkDll = NULL;
PFRUNGATEFRAMEWORKPWDRESET pfRunGateFrameworkPwdReset = NULL;
PWSTR domain = NULL;
PWSTR username = NULL;
PWSTR separator = NULL;
PWSTR input_username;
// Get the HWnd of the parent
if (FAILED(_pCredProvCredentialEvents->OnCreatingWindow(&phwndOwner)))
{
phwndOwner = NULL;
}
if (FAILED(SHStrDupW(_rgFieldStrings[SFI_USERNAME], &input_username)))
{
MessageBox(
phwndOwner,
_T("Fail: SHStrDupW(_rgFieldStrings[SFI_USERNAME], &input_username)"),
_T("Error"),
MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL
);
goto FAIL;
}
if (!input_username || *input_username == '\0')
{
MessageBox(
phwndOwner,
_T("Please input Username"),
_T("Error"),
MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL
);
goto FAIL;
/////////////////////////////////////////////////////////////////
//DialogBox();
////////////////////////////////////////////////////////////////
}
//if ((separator = wcschr(input_username, '\\')) != NULL)
//{
// // assume input is in the form of domain\username
// *separator = '\0';
// domain = input_username;
// username = separator + 1;
//}
//else if ((separator = wcschr(input_username, '@')) != NULL)
//{
// // assume input is in the form of UPN
// domain = NULL;
// username = input_username;
//}
//else
//{
// MessageBox(
// phwndOwner,
// _T("Please input Domain\\Username or UPN"),
// _T("Error"),
// MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL
// );
// goto FAIL;
//}
//Ilantus
//fetchPortalURL((WCHAR)username);
//// Load the GateFramework dll
//hGateFrameworkDll = LoadLibrary(GATE_FRAMEWORK_MODULE);
//if (!hGateFrameworkDll)
//{
// MessageBox(
// phwndOwner,
// _T("Fail: LoadLibrary(GATE_FRAMEWORK_MODULE)"),
// _T("Error"),
// MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL
// );
// goto FAIL;
//}
//pfRunGateFrameworkPwdReset = (PFRUNGATEFRAMEWORKPWDRESET)GetProcAddress(hGateFrameworkDll, "RunPwdReset");
//if (!pfRunGateFrameworkPwdReset)
//{
// MessageBox(
// phwndOwner,
// _T("Fail: GetProcAddress(hGateFrameworkDll, \"RunPwdReset\")"),
// _T("Error"),
// MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL
// );
// goto FAIL;
//}
//pfRunGateFrameworkPwdReset(phwndOwner, domain, username, L"en-US");
FAIL:
if (input_username)
{
CoTaskMemFree(input_username);
}
if (hGateFrameworkDll)
{
FreeLibrary(hGateFrameworkDll);
}
return E_FAIL;
}
// ReportResult is completely optional. Its purpose is to allow a credential to customize the string
// and the icon displayed in the case of a logon failure. For example, we have chosen to
// customize the error shown in the case of bad username/password and in the case of the account
// being disabled.
HRESULT PasswordResetCredential::ReportResult(
NTSTATUS ntsStatus,
NTSTATUS ntsSubstatus,
PWSTR* ppwszOptionalStatusText,
CREDENTIAL_PROVIDER_STATUS_ICON* pcpsiOptionalStatusIcon
)
{
UNREFERENCED_PARAMETER(ntsStatus);
UNREFERENCED_PARAMETER(ntsSubstatus);
UNREFERENCED_PARAMETER(ppwszOptionalStatusText);
UNREFERENCED_PARAMETER(pcpsiOptionalStatusIcon);
return E_NOTIMPL;
}
|
|
|
|
|
The third parameter to DialogBox is still NULL - DialogBox((HINSTANCE)g_hinst, MAKEINTRESOURCE(IDD_DIALOG1),NULL, InputBox_WndProc);
You need to specify the handle to the parent window here.
|
|
|
|
|
hi all,
i am DrawText on My Cdialog, i want to set color according to the Text Color of Title bar caption.
so is there any option to get the color of text of Title Bar.
i also chk the GetSysColor but no success is in hand..
thanks in advance.
|
|
|
|
|
|
i m tyring COLOR_CAPTIONTEXT and COLOR_INACTIVECAPTIONTEXT but it return some other color...
|
|
|
|
|
I just tried the same and those colours are both correct on my system.
|
|
|
|
|
oops sorry its my mistake...its done now..
modified 11-Feb-13 5:27am.
|
|
|
|
|
Hi,
Using the GetProcAdress I wanted to get the exported address of a function
When it returned zero I double checked with depends.exe to ensure the function was exported
I then went to assembly mode to see what happens and noticed that after the call statement a value was returned in the RAX register but there wasn't any code to move the RAX register value to my FARPROC data member
I then turned optimization off #pragma optimize("",off) and the same code generated "mov FARPROC,rax" am I missing some compiler to flag to make this happen without turning optimization off
Thanks
Thanks
|
|
|
|
|
It would help if you could post the code in your function and some of the generated assembly code.
|
|
|
|
|
Here it is
HMODULE hutil_module;
FARPROC hercgui_addr;
hutil_module = GetModuleHandle("HENGINE");
With #pragma optimize("",off)
hercgui_addr = GetProcAddress(hutil_module,"hercgui_proc");
000000005178D4BC lea rdx,[string "hercgui_proc" (518672B0h)]
000000005178D4C3 mov rcx,qword ptr [rsp+0E0h]
000000005178D4CB call qword ptr [__imp_GetProcAddress (5184A050h)]
000000005178D4D1 mov qword ptr [rsp+0C0h],rax
with optimization on
hercgui_addr = GetProcAddress(hutil_module,"hercgui_proc");
00000000514CD44B lea rdx,[string "hercgui_proc" (515A42B0h)]
00000000514CD452 mov rcx,rax
00000000514CD455 call qword ptr [__imp_GetProcAddress (51587050h)]
Thanks
|
|
|
|
|
Do you actually use
hercgui_addr later in the code? I find that if I'm looking at optimized assembly output that if I don't actually use the value for something, the extra processing code can get discarded. At a minimum, you can dump the value to console or screen to make sure the code remains in the optimized assembly output.
|
|
|
|
|
This is the next statement
strncpy(&herc_parm[0],&hercgui_addr,8);
I am running X64
I send thid address to child process
return_code = CreateProcess((LPCSTR) &herc_command[0], (LPCSTR) &herc_parm[0], (LPCSTR) &sa,
NULL,
TRUE,
(DWORD) NULL,
NULL,
NULL,
&si,
&pi);
Later in the child process I Create a Remote thread with the parent
snap_shot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
process32.dwSize = sizeof(PROCESSENTRY32);
return_cde = Process32First(snap_shot,&process32);
pid = GetCurrentProcessId();
while(pid != process32.th32ProcessID)
{
return_cde = Process32Next(snap_shot,&process32);
}
herc_process = process32.th32ParentProcessID;
my_herc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,herc_process); if (my_herc == NULL)
errcd= GetLastError();
SECURITY_ATTRIBUTES sa;
LPVOID lparam;
DWORD threadid;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
lparam = NULL;
CreateRemoteThread(my_herc,
&sa,
NULL,
(LPTHREAD_START_ROUTINE) hercgui,
lparam,
NULL,
&threadid);
|
|
|
|
|
ForNow wrote: When it returned zero I double checked with depends.exe to ensure the function was exported Did you actually check what error was being generated, as described in the function's documentation[^]?
|
|
|
|
|
Richard
look at what happens When I turn optimazation off and check for an error no code is generated
for the if (hercgui_addr = NULL) one wierd complier
On aonther issue my assignment at work I was able to resolve the 800A30EC I think thats it
by Doing app.GetActiveWorkBook however txt file wasn't displayed in the workbook in fact
a worksheet wasn't loaded I was under the impression that OpenText loads a worksheet as well
Thanks
hercgui_addr = GetProcAddress(hutil_module,"hercgui_proc");
00000000013FD44B lea rdx,[string "hercgui_proc" (14D42B0h)]
00000000013FD452 mov rcx,rax
00000000013FD455 call qword ptr [__imp_GetProcAddress (14B7050h)]
if (hercgui_addr = NULL)
errcd = GetLastError();
|
|
|
|
|
if (hercgui_addr = NULL)
This sets the value of hercgui_addr to NULL , so it is little wonder that the generated code does not look correct.
|
|
|
|
|
Thanks once I referenced hercgui eith "=="
the optimized version genereted the "mov hercgui,rax"
Thanks again
|
|
|
|
|
I'm just trying to understand the Microsoft specific modifier __interface.
According to the MSDN, "__interface implies the novtable __declspec modifier."
However, when I try to mock up code to try an verify this, Visual Studio 2008 still suggests the vtable pointer is present?
__interface ISample
{
bool Next();
bool Prev();
};
class CSample : public ISample
{
public:
bool Next()
{
return false;
}
bool Prev()
{
return false;
}
};
Am I misunderstanding what MSDN is trying to convey or am I just doing something wrong. In a nutshell, just trying to see if it's possible to enforce interface rules without needing the vtable overhead if only deriving from __interface declarations. I understand that this would not be portable code.
|
|
|
|
|
I have to think hard about this every time I look at this type of problem. I think the answer is that ISample is never concrete so it doesn't need a vtable. There is a vtable in CSample. When you call either of the 2 methods through a pointer (either CSample* or ISample*), the vtable needs are met by the concrete class.
--
Harvey
|
|
|
|
|
Thanks for responding. I guess my confusion is if __interface hints to the compiler that the base class will never be instantiated, even though __interface supposedly makes the methods pure virtual, I was hoping that the interface rules were being enforced at compile time and the virtualness of the base class declarations would not propagate up to the derived class, unless of course the derived class explicitly declared something virtual. I know that kinda flies in the face of the normal rules for virtual but I was hoping there was a way to get interface rules enforcement without literally applying the virtual rules unless explicit outside of the interface.
I was hoping that CSample, in this case, would be treated at runtime like it did not have a base class and did not have any virtual methods, and thus the compiler would discard the vtable for it as well.
Is the vtable really needed (in this scenario)?
|
|
|
|
|
novtable is used in case of hardcore optimizations with "abstract" base classes are never instantiated. An interface is always abstract by definition.
To understande novtable first you have to understand a bit more about how a derived class is instantiated and initialized. Let me explain this with a simple example:
A
/ \
B C
/ \
D E
The above drawing is a class hierarchy and we will examine the instantiation of the D class. Lets assume that A already has at least one virtual method so it has a vtable as well. What you have learnt about C++ is that "new D; " calls constructors A, C and D in this order. Now we delve into the implementation details and check out some interesting stuff. The simple truth is that the only thing that the compiler calls in case of "new D; " is the constructor of D. BUT every constructor starts with some auto generated stuff by the compiler that is followed by the "user defined constructor code".
Let's see some pseudo code:
constructor_D()
{
auto-generated: call constructor_C()
auto-generated: init the vtable to vtable-D
user-defined constructor code of D
}
constructor_C()
{
auto-generated: call constructor_A()
auto-generated: init the vtable to vtable-C
user-defined constructor code of C
}
constructor_A()
{
auto-generated: init the vtable to vtable-A
user-defined constructor code of A
}
So if we consider only the "user defined constructor code" then the order of constructor calls is indeed A C D, but if we look at the whole stuff then its D C A. Its obvious that initializing the vtable more than once for an instance is superfluous, in the above example its initialzed 3 times, first in A, then in C and finially in D. We need the initialization only in D because we created a D instance so we need the virtual methods for the D class. Unfortunately sometimes the compiler can not find out whether the vtable initialization in A and C are superfluous or not so it generates the vtable init code there, but you can add the novtable to class A and C as an optimization if you know that they will never be instantiated. In case of an interface we know that it will never be instantiated so an automatic novtable optimization is obvious, an interface will have at least one descendant to init the final vtable pointer.
In your example the ISample interface simply doesn't have a constructor and your CSample constructor looks like this:
constructor_CSample()
{
auto-generated: init the vtable to vtable-CSample
user-defined constructor code of CSample
}
This is why you have the vtable there.
There is a golden rule that calling a virtual function from a constructor directly or indirectly is a bad practice. Direct calls can be caught by the compiler, but indirect ones silently cause bugs and headaches. On indirect virtual function call I mean: you call a non-virtual function from the constructor and then that non-virtual function calls a virtual one. Why is this a problem? Lets say you call a virtual function from the constructor of C. When the constructor of C runs the vtable is initialized to the vtable of class C. This means that even if class D overrides the virtual function, the virtual function of C executes because we have only the vtable of C when constructor C runs!!! This causes a hard to find bug without crash!!! If you use the novtable with class C then the vtable is not initialized when constructor C runs so there are 3 possible scenarios:
1. The vtable pointer might be uninitialized because C and its base classes left it uninitialized so the virtual function call causes a crash.
2. One of the base classes of C doesn't have the novtable directive so it filled in the vtable. In this case if the vtable of this particular base class has an entry for the called virtual function then this virtual function will be executed (A), otherwise a crash occurs (B).
In my opinion a crash is always better and easier to find than unwanted behavior.
So, you can use novtable with any "abstract" class as an optimization. In case of novtable we can treat any classes "abstract" that won't be instantiated at runtime - for example we can use novtable relatively safely with a class whos constructor is has protected access modifier but care must be taken not to call a virtual function from the constructor directly or indirectly. Note that I worked on performance critical programs but I never reached a point where I started to use novtable to optimize. My humble opinion is that if your performance problems come from vtable initializations then you are doing something wrong. Performance problems are rather the consequences of algorithmic problems and cache-unfriendly memory access.
EDIT: you can't enforce interface rules with other mayor C++ compilers. Even if you define the __interface keyword to nothing with other compilers, you have to put there the virtual keyword for functions and either a dummy implementation or "= 0".
|
|
|
|
|