I have an error and I don´t have idea what´s the problem.
I'm trying to compile one example of Open NFC for a project. The example is test_ndef_url. I do not know if the problem to a coding error or a library of windows is due, shellapi.h.
Test_ndef_url code is:
/*
* Copyright (c) 2007-2012 Inside Secure, All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*******************************************************************************
Implementation of the Example 1 for Open NFC.
*******************************************************************************/
/* Allow use of features specific to Windows XP or later. */
#ifndef _WIN32_WINNT
/* Change this to the appropriate value to target other versions of Windows. */
#define _WIN32_WINNT 0x0601
#endif
/* Suppress many files from the compilation */
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#include "shellapi.h"
#include <stdio.h>
#include <stdlib.h>
#include "open_nfc.h"
#include "win32_test_core.h"
/* Type definititions */
/* ------------------ */
/* Local prototypes */
/* ---------------- */
/* Global variables */
/* ---------------- */
struct __testContext
{
char16_t* pURL;
bool_t bVirtualTag;
bool_t bReadTest;
W_HANDLE hRegistry;
} ;
struct __testContext g_testCtx = { null, W_FALSE, W_FALSE, W_NULL_HANDLE };
/* Callback function of type tWBasicGenericHandleCallbackFunction */
static void ReadMessageOnAnyTagCompletedURL(void *pCallbackParameter, W_HANDLE hMessage, W_ERROR nError)
{
if(nError == W_SUCCESS)
{
W_HANDLE hRecord = WNDEFGetRecord(hMessage, 0);
WBasicCloseHandle(hMessage);
if(WRTDIsURIRecord(hRecord))
{
char16_t aURIValue[256];
if(WRTDURIGetValue(hRecord, (char16_t*)&aURIValue, 256) == W_SUCCESS)
{
printf("The URL read in the tag is \"%S\"\n", aURIValue);
ShellExecute(NULL, L"open", (char16_t*)aURIValue, NULL, NULL, SW_SHOWNORMAL);
}
}
else
{
printf("Error URL: Error detected in the tag message.\n");
}
WBasicCloseHandle(hRecord);
}
else if(nError == W_ERROR_ITEM_NOT_FOUND)
{
printf("Error URL: This tag does not contain a message of the right type.\n");
}
else if(nError == W_ERROR_TIMEOUT)
{
printf("Error URL: Lost the communication with the tag.\n");
}
else
{
printf("Error URL: Error 0x%08X returned during the tag detection.\n", nError);
}
printf("Present a new tag to be read or press Ctrl+C to stop the application\n");
}
/* Callback function of type tWBasicGenericCallbackFunction */
static void WriteMessageOnAnyTagCompleted(void *pCallbackParameter, W_ERROR nError)
{
switch(nError)
{
case W_SUCCESS:
printf("The message is written in the tag.\n");
break;
case W_ERROR_LOCKED_TAG:
printf("The operation failed because the tag is locked.\n");
break;
case W_ERROR_TAG_FULL:
printf("The message is too large for the remaining free space in the tag.\n");
break;
default:
printf("An error occured during the writing operation (code 0x%x)\n", nError);
break;
}
StopApplication();
}
/* Receive the event of the virtual tag */
static void VirtualTagEventHandler(void *pCallbackParameter, uint32_t nEventCode)
{
switch(nEventCode)
{
case W_VIRTUAL_TAG_EVENT_SELECTION:
printf("The tag is selected by the reader.\n");
break;
case W_VIRTUAL_TAG_EVENT_READER_LEFT:
printf("The reader left the tag without reading the content.\n");
break;
case W_VIRTUAL_TAG_EVENT_READER_READ_ONLY :
printf("The reader read the tag.\nPresent again a reader to read the virtual tag or press Ctrl+C to stop the application\n");
break;
case W_VIRTUAL_TAG_EVENT_READER_WRITE:
default:
printf("This event should not occur for a read-only virtual tag.\n");
break;
}
}
/**
* GetSpecificTestSyntax
*
* #return String describing the command line syntax specific to this test
**/
char16_t * GetSpecificTestSyntax( void )
{
return L"[url <URL> | virtualurl <URL>\n"
L" - If the parameter is not present, the application waits to read a tag with an URL.\n"
L" - If \"url\" is present, the application waits for a Tag to write the URL.\n"
L" - If \"virtualurl\" is present, the application simulates a tag containing the URL.\n\n"
L"The following tags are supported: Type 2, Type 4-A, Type 4-B, Type 5-2K, Type 5-32K and Type 6.\n\n" ;
}
/**
* VerifyTestConditions
*
* #param[in] nArgc number of arguments
*
* #param[in] pArgv arguments array
*
* #return W_SUCCESS Arguments syntax is correct
* W_ERROR_xxx is syntax error is detected
**/
W_ERROR VerifyTestConditions( int32_t nArgc, char16_t* pArgv[] )
{
if(nArgc == 3)
{
if(wcscmp(pArgv[1], L"url") == 0)
{
g_testCtx.pURL = pArgv[2];
}
else if(wcscmp(pArgv[1], L"virtualurl") == 0)
{
g_testCtx.bVirtualTag = W_TRUE;
g_testCtx.pURL = pArgv[2];
}
else
{
nArgc = 0;
}
}
if((nArgc != 1) && (nArgc != 3))
{
return W_ERROR_BAD_PARAMETER;
}
g_testCtx.bReadTest = (nArgc == 1) ? W_TRUE : W_FALSE ;
return W_SUCCESS;
}
/**
* LaunchTest
*
**/
W_ERROR LaunchTest( void )
{
W_HANDLE hMessage = W_NULL_HANDLE;
if(g_testCtx.bReadTest != W_FALSE)
{
WNDEFReadMessageOnAnyTag(ReadMessageOnAnyTagCompletedURL, null, W_PRIORITY_MAXIMUM,
W_NDEF_TNF_WELL_KNOWN, L"U", &g_testCtx.hRegistry);
printf("Present the tag to be read or press Ctrl+C to stop the application\n");
}
else
{
if(WNDEFCreateNewMessage(&hMessage) != W_SUCCESS)
{
printf("Error: Cannot create the new message.\n");
goto return_function;
}
if(WRTDURIAddRecord(hMessage, g_testCtx.pURL) != W_SUCCESS)
{
printf("Error: Cannot add the URI record in the message.\n");
goto return_function;
}
if(g_testCtx.bVirtualTag == W_FALSE)
{
printf("Ready to write the URL \"%S\"\n", g_testCtx.pURL);
WNDEFWriteMessageOnAnyTag(WriteMessageOnAnyTagCompleted, null, W_PRIORITY_MAXIMUM, hMessage, W_NDEF_ACTION_BIT_ERASE | W_NDEF_ACTION_BIT_FORMAT_ALL, &g_testCtx.hRegistry);
printf("Present the tag to be written or press Ctrl+C to stop the application\n");
}
else
{
W_ERROR nError;
W_HANDLE hVirtualTag;
static const uint8_t aPUPI[] = { 0x01, 0x02, 0x03, 0x04 };
printf("Ready to simulate a tag with the URL \"%S\"\n", g_testCtx.pURL);
/* Create the virtual tag, the maximum length is set to the size of the message */
nError = WVirtualTagCreate(W_PROP_NFC_TAG_TYPE_4_B, aPUPI, sizeof(aPUPI),
WNDEFGetMessageLength(hMessage), &hVirtualTag);
if(nError != W_SUCCESS)
{
printf("Cannot create the virtual tag\n");
}
else
{
/* Write the message in the virtual tag */
nError = WNDEFWriteMessageSync(hVirtualTag, hMessage, W_NDEF_ACTION_BIT_ERASE | W_NDEF_ACTION_BIT_LOCK | W_NDEF_ACTION_BIT_FORMAT_ALL);
if(nError != W_SUCCESS)
{
printf("Cannot write the message in the virtual tag\n");
WBasicCloseHandle(hVirtualTag);
}
else
{
/* Start the tag simulation */
nError = WVirtualTagStartSync(hVirtualTag, VirtualTagEventHandler, null, W_TRUE);
if(nError != W_SUCCESS)
{
printf("Cannot activate the virtual tag\n");
WBasicCloseHandle(hVirtualTag);
}
else
{
printf("Present a reader to read the virtual tag or press Ctrl+C to stop the application\n");
}
}
}
}
}
return_function:
WBasicCloseHandle(hMessage);
/* Go pending on WaitForSingleObject (Card/Tag operation completed or Ctrl-C) */
return W_SUCCESS;
}
/**
* CloseTest
*
**/
void CloseTest( void )
{
WBasicCloseHandle( g_testCtx.hRegistry );
}
The part of the code is defined shellapi.h where ShellExecute is:
#include <winapifamily.h>
/*****************************************************************************\
* *
* shellapi.h - SHELL.DLL functions, types, and definitions *
* *
* Copyright (c) Microsoft Corporation. All rights reserved. *
* *
\*****************************************************************************/
#ifndef _INC_SHELLAPI
#define _INC_SHELLAPI
#include <SpecStrings.h>
//
// Define API decoration for direct importing of DLL references.
//
#ifndef WINSHELLAPI
#if !defined(_SHELL32_)
#define WINSHELLAPI DECLSPEC_IMPORT
#else
#define WINSHELLAPI
#endif
#endif // WINSHELLAPI
#ifndef SHSTDAPI
#if !defined(_SHELL32_)
#define SHSTDAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE
#define SHSTDAPI_(type) EXTERN_C DECLSPEC_IMPORT type STDAPICALLTYPE
#else
#define SHSTDAPI STDAPI
#define SHSTDAPI_(type) STDAPI_(type)
#endif
#endif // SHSTDAPI
#ifndef SHDOCAPI
#if !defined(_SHDOCVW_)
#define SHDOCAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE
#define SHDOCAPI_(type) EXTERN_C DECLSPEC_IMPORT type STDAPICALLTYPE
#else
#define SHDOCAPI STDAPI
#define SHDOCAPI_(type) STDAPI_(type)
#endif
#endif // SHDOCAPI
#if !defined(_WIN64)
#include <pshpack1.h>
#endif
#ifdef __cplusplus
extern "C" { /* Assume C declarations for C++ */
#endif /* __cplusplus */
#pragma region Desktop Family
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
DECLARE_HANDLE(HDROP);
_Success_(return != 0)
SHSTDAPI_(UINT) DragQueryFileA(_In_ HDROP hDrop, _In_ UINT iFile, _Out_writes_opt_(cch) LPSTR lpszFile, _In_ UINT cch);
_Success_(return != 0)
SHSTDAPI_(UINT) DragQueryFileW(_In_ HDROP hDrop, _In_ UINT iFile, _Out_writes_opt_(cch) LPWSTR lpszFile, _In_ UINT cch);
#ifdef UNICODE
#define DragQueryFile DragQueryFileW
#else
#define DragQueryFile DragQueryFileA
#endif // !UNICODE
SHSTDAPI_(BOOL) DragQueryPoint(_In_ HDROP hDrop, _Out_ POINT *ppt);
SHSTDAPI_(void) DragFinish(_In_ HDROP hDrop);
SHSTDAPI_(void) DragAcceptFiles(_In_ HWND hWnd, _In_ BOOL fAccept);
SHSTDAPI_(HINSTANCE) ShellExecuteA(_In_opt_ HWND hwnd, _In_opt_ LPCSTR lpOperation, _In_ LPCSTR lpFile, _In_opt_ LPCSTR lpParameters,
_In_opt_ LPCSTR lpDirectory, _In_ INT nShowCmd);
SHSTDAPI_(HINSTANCE) ShellExecuteW(_In_opt_ HWND hwnd, _In_opt_ LPCWSTR lpOperation, _In_ LPCWSTR lpFile, _In_opt_ LPCWSTR lpParameters,
_In_opt_ LPCWSTR lpDirectory, _In_ INT nShowCmd);
#ifdef UNICODE
#define ShellExecute ShellExecuteW
#else
#define ShellExecute ShellExecuteA
#endif // !UNICODE
_Success_(return > 32) // SE_ERR_DLLNOTFOUND
SHSTDAPI_(HINSTANCE) FindExecutableA(_In_ LPCSTR lpFile, _In_opt_ LPCSTR lpDirectory, _Out_writes_(MAX_PATH) LPSTR lpResult);
_Success_(return > 32) // SE_ERR_DLLNOTFOUND
SHSTDAPI_(HINSTANCE) FindExecutableW(_In_ LPCWSTR lpFile, _In_opt_ LPCWSTR lpDirectory, _Out_writes_(MAX_PATH) LPWSTR lpResult);
#ifdef UNICODE
#define FindExecutable FindExecutableW
#else
#define FindExecutable FindExecutableA
And that tells me the error Microsoft Visual Studio 2013 is:
Warning 1 warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/SAFESEH' specification File:win32_test_core.obj Project:test_ndef_url
Error 2 error LNK2019: unresolved external symbol __imp__ShellExecuteW#24 referenced in function _ReadMessageOnAnyTagCompletedURL File:win32_test_ndef_url.obj Project:test_ndef_url
Error 3 error LNK1120: 1 unresolved externals File:test_ndef_url.exe Project:test_ndef_url
Please, I need help with this.
You are missing the actual body (or a placeholder for a function body) of the ShellExecute function (OK, ShellExecuteW, but that's a detail you don't need to worry about now.) What's in the header is the declaration, but you still need the definition. In this case, that's in a library.
Do these:
Google for "MSDN ShellExecute". MSDN is Microsoft Developer Network, and the place to go for Windows API documentation.
The first link is to https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153%28v=vs.85%29.aspx (for now; Microsoft's websites have been awful at keeping links stable for future reference.)
That's the documentation of the function. Scroll down to the bottom of the page. There is a table that lists the "requirements" for this function. One of them is the "Library", which is "Shell32.lib" in this case.
You need to link to this library. The easiest way, in Visual C++ (which you are using) and for a standard Windows library (which this is) is to add the following line to one of your source files (maybe at the very top): #pragma comment (lib, "Shell32"). (Note the lack of a semicolon.)
and that's it. There are better (more scalable, flexible and portable) methods for larger projects, but you should be fine for this small sample.
Related
I have imported an Activex component (*.ocx) on Embarcadero C++Builder 10.2 when I build the program I get this warning "Warning W8127 Function defined with different linkage".
Can any one tell me how I can resolve this issue.
My code is below:
#include <vcl.h>
#pragma hdrstop
#include <System.Win.ComServ.hpp>
#include <axbase.h>
#include <olectl.h>
#pragma package(smart_init)
#pragma link "System.Win.ComServ"
#pragma package(smart_init)
#pragma link "System.Win.ComServ"
// -----------------------------------------------------------------------------
// Entry point of your Server invoked by Windows for processes or threads are
// initialized or terminated.
//
// -----------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
return TRUE;
}
// -----------------------------------------------------------------------------
// Entry point of your Server invoked to inquire whether the DLL is no
// longer in use and should be unloaded.
// -----------------------------------------------------------------------------
STDAPI __export DllCanUnloadNow(void)
{
Comserv::TComServer* comserver = Comserv::GetComServer();
return (!comserver ||
((comserver->ObjectCount /* + comserver->FactoryCount */) == 0)) ?
S_OK : S_FALSE;
}
// -----------------------------------------------------------------------------
// Entry point of your Server allowing OLE to retrieve a class object from
// your Server
// -----------------------------------------------------------------------------
STDAPI __export DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
Comobj::TComObjectFactory* Factory = Comobj::ComClassManager()->GetFactoryFromClassID(rclsid);
if (Factory)
{
if (Factory->GetInterface(riid, ppv))
return S_OK;
else
return E_NOINTERFACE;
}
else
{
*ppv = 0;
return CLASS_E_CLASSNOTAVAILABLE;
}
}
// -----------------------------------------------------------------------------
// Entry point of your Server invoked to instruct the server to create
// registry entries for all classes supported by the module
// -----------------------------------------------------------------------------
STDAPI __export DllRegisterServer(void)
{
Comserv::TComServer* comserver = Comserv::GetComServer();
if (comserver)
{
try
{
comserver->LoadTypeLib();
comserver->UpdateRegistry(true);
return S_OK;
}
catch(...)
{
return E_FAIL;
}
}
else
{
return E_FAIL;
}
}
// -----------------------------------------------------------------------------
// Entry point of your Server invoked to instruct the server to remove
// all registry entries created through DllRegisterServer.
// -----------------------------------------------------------------------------
STDAPI __export DllUnregisterServer(void)
{
Comserv::TComServer* comserver = Comserv::GetComServer();
if (comserver)
{
try
{
comserver->LoadTypeLib();
comserver->UpdateRegistry(false);
return S_OK;
}
catch(...)
{
return E_FAIL;
}
}
else
{
return E_FAIL;
}
}
// ------------------------------------------------------------------------------
// Entry point of your Server installation/setup. Used for 'PerUser' registration
// Invoked via call to "regsvr32 /n /i:user [/u] axlibrary.dll"
// ------------------------------------------------------------------------------
STDAPI __export DllInstall(BOOL bInstall, LPCWSTR pszCmdLine)
{
Comserv::TComServer* comserver = Comserv::GetComServer();
if (comserver)
{
bool savePerUser = comserver->PerUserRegistration;
if (pszCmdLine && !StrIComp(pszCmdLine, L"user"))
comserver->PerUserRegistration = true;
else
comserver->PerUserRegistration = false;
HRESULT result = E_FAIL;
if (bInstall)
{
result = DllRegisterServer();
if (result == E_FAIL)
DllUnregisterServer();
}
else
result = DllUnregisterServer();
comserver->PerUserRegistration = savePerUser;
return result;
}
else
{
return E_FAIL;
}
}
The functions DllCanUnloadNow() and DllGetClassObject are declared in this header file "comebaseapi.h" as follow:
_Check_return_
STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID FAR* ppv);
__control_entrypoint(DllExport)
STDAPI DllCanUnloadNow(void);
The functions DllRegisterServer() and DllUnregisterServer() are declared in this header file "olectl.h" as follow:
__control_entrypoint(DllExport)
STDAPI DllRegisterServer(void);
__control_entrypoint(DllExport)
STDAPI DllUnregisterServer(void);
The function DllInstall() is declared in this header file "shlwapi.h" as follow:
// DllInstall (to be implemented by self-installing DLLs)
STDAPI DllInstall(BOOL bInstall, _In_opt_ PCWSTR pszCmdLine);
I thank you for your support.
I'm new to c++ and vc++ and i used 3rd party library bioapi. I successfully integrated it but when I tried to use the sample working program of bioapi, the misc.h and misc.cpp, i got an error LNK2005 AND LNK1160.
By the way I created this as CLR project in vc++ and it seems I cannot use /FORCE or /FORCE:MULTIPLE.
Here's the misc.h
/*---------------------------------------------------------------*/
/* */
/* Copyright (C) NEC Corporation 2011 */
/* NEC CONFIDENTIAL AND PROPRIETARY */
/* */
/* All rights reserved by NEC Corporation. This program must be */
/* used solely for the purpose for which it was furnished by NEC */
/* Corporation. No part of this program may be reproduced or */
/* disclosed to others, in any form, without the prior written */
/* permission of NEC Corporation. Use of copyright notice does */
/* not evidence publication of this program. */
/* */
/* NEC Corporation accepts no responsibility for any damages */
/* resulting from the use of this sample code. */
/* This sample code is provided "AS IS", and its user assume all */
/* risks when using it. */
/* */
/*---------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <sys/types.h> /* for stat() */
#include <sys/stat.h> /* for stat() */
#include <direct.h> /* for _mkdir() */
//#include "stdafx.h"
//#include "resource.h"
#include "BioAPI.h" /* include BioAPI Framework */
#include "BioAPI_util.h" /* include BioAPI Framework */
#include "hf-pid-bsp.h"
/*--------------------------------------------------------------------
*
* define
*
*--------------------------------------------------------------------*/
#define MaxN 1000 /* Max Identify Num */
#define MaxEnrollNum 999 /* Max Enroll Num */
#define MaxID 9999 /* Max Enroll ID */
#define MinID 0 /* Min Enroll ID */
#define Timeout 10000 /* Capture Timeout */
#define ERRCODE_ID_INPUT_ERROR -100
#define ERRCODE_NOT_ENROLLED -101
#define SECTION_IDENTIFYPARAM "IdentifyParam"
#define KEY_MAXNUMBEROFRESULTS "MaxNumberOfResults"
#define MESS_ALLEADY_STARTED "Application is already started."
#define MESS_USERREG "UserReg"
#define MESS_AP_ERROR "Error"
#define MESS_ID_INPUT_ERROR TEXT("Please input a value in the range of 0001-9999")
#define MESS_NOT_ENROLLED TEXT("The ID does not exist for")
#define MESS_BIOAPI_ERROR TEXT("BioAPI Error")
#define MESS_BIOAPI_ERROR_CODE TEXT("BioAPI Error Code: %ld")
#define MESS_ENROLL "Enrollment"
#define MESS_ENROLL_FAILED "Enroll process is failed."
#define MESS_ENROLL_SUCCESSED "Enroll process is successed."
#define MESS_VERIFY "Verification"
#define MESS_VERIFY_FAILED "Verification failed."
#define MESS_VERIFY_OK "Verification process is successed."
#define MESS_VERIFY_NG "Verification process is failed."
#define MESS_IDENTIFY "Identification"
#define MESS_IDENTIFY_FAILED "Identification failed."
#define MESS_IDENTIFY_OK "Identification process is successed."
#define MESS_IDENTIFY_NG "Identification process is failed."
#define MESS_CAPTION "Sample Application"
#define MESS_END "Exit"
#define MESS_MESSAGE1 "Please choose the function."
#define MESS_CLOSE "Close"
#define MESS_ENROLL1 "Enroll"
#define MESS_ENROLL2 "CreateTemplate"
#define MESS_MESSAGE2 "After entering ID(0001`9999), Please click [Enroll] button or [CreateTemplate] button."
#define MESS_ID "ID:"
#define MESS_ONETOONE "1:1 Verification"
#define MESS_ONETON "1:N Identification"
#define MESS_MESSAGE3 "Please choose the verification method."
#define MESS_VERIFY1 "VerifyMatch"
#define MESS_VERIFY2 "Verify"
#define MESS_MESSAGE4 "After entering ID(0001`9999), Please click [Verify] button or [Verification] button."
#define MESS_IDENTIFY1 "IdentifyMatch"
#define MESS_IDENTIFY2 "Identify"
#define MESS_MESSAGE5 "Please click [Identify] button or [Identification] button."
#define MESS_AUTH_MESSAGE "Identification process is successed.\r\nMaxNumberOfResults = (%d)\r\nNumberOfResults = (%d)\r\nID:"
#define MESS_INIFILE_GET_FAILED "sample.ini get failed."
#define PATH_ENROLLED_FILE ".\\enroll\\*.dat"
#define PATH_ENROLLED_FILE_IN_ID ".\\enroll\\%04d_*.dat"
#define PATH_ENROLLED_DIRECTORY ".\\enroll"
#define PATH_ENROLLED_NAME TEXT(".\\enroll\\%s_%03d.dat")
#define PATH_ENROLLED_DIRECTORY ".\\enroll"
#define INIFILE_NAME ".\\sample.ini"
/*--------------------------------------------------------------------
*
* global
*
*--------------------------------------------------------------------*/
static BioAPI_HANDLE gModuleHandle;
static BioAPI_RETURN bioReturn;
static BioAPI_BIR_HANDLE StoredTemplate;
static BioAPI_INPUT_BIR CapturedBIR;
static BioAPI_INPUT_BIR ProcessedBIR;
static BioAPI_INPUT_BIR StoredBIR;
static BioAPI_BIR_HANDLE CapturedTemplate;
static BioAPI_BOOL boolie = BioAPI_FALSE;
static BioAPI_BOOL result;
static BioAPI_FRR frr = HF_PID_BSP_LEVEL_MIDDLE; // Security Level
static BioAPI_FAR AchievedFAR = 1;
static uint32 MaxNumberOfResults = 1;
static uint32 NumberOfResults;
static BioAPI_CANDIDATE_ARRAY_PTR Candidates;
static BioAPI_INPUT_BIR InputBirProcessed_PopulationElem[MaxN];
static BioAPI_IDENTIFY_POPULATION *Population;
static BioAPI_BIR_PTR lpPopulationAryBIRData_Member;
static HANDLE hSearch;
static char fname_db[MAX_PATH + 1];
static char fid_db[MAX_PATH + 1];
static WIN32_FIND_DATA fd;
static BioAPI_BIR_ARRAY_POPULATION lPopulationAryBIRData;
static BioAPI_BIR_PTR FullBIR;
static BioAPI_UUID BSPUuid = HF_PID_BSP_UUID;
typedef struct stBIR_AND_FileName {
BioAPI_BIR* pPopulationBIRPointer;
char lptszUserName[_MAX_PATH];
}BIR_AND_FILENAME;
static BIR_AND_FILENAME RetBIR_And_FileName[MaxN];
static BioAPI_CANDIDATE_ARRAY lpWorkCandidates;
static char IdentificationMessage[MAX_PATH + 1];
/*--------------------------------------------------------------------
*
* function
*
*--------------------------------------------------------------------*/
void PrintErrorCode(BioAPI_RETURN bioReturn);
void LoadBSP(BioAPI_HANDLE_PTR gModuleHandle);
void ReleaseBSP(BioAPI_HANDLE_PTR gModuleHandle);
BioAPI_RETURN OutputToFile(BioAPI_HANDLE gModuleHandle, LPTSTR lptszUserName, BioAPI_BIR_HANDLE BirHandle);
BioAPI_RETURN InputFromFile(LPTSTR lptszUserName, BioAPI_INPUT_BIR * InputBir, uint32 count);
/*--------------------------------------------------------------------
*
* End of misc.h
*
*--------------------------------------------------------------------*/
misc.cpp
/*---------------------------------------------------------------*/
/* */
/* Copyright (C) NEC Corporation 2011 */
/* NEC CONFIDENTIAL AND PROPRIETARY */
/* */
/* All rights reserved by NEC Corporation. This program must be */
/* used solely for the purpose for which it was furnished by NEC */
/* Corporation. No part of this program may be reproduced or */
/* disclosed to others, in any form, without the prior written */
/* permission of NEC Corporation. Use of copyright notice does */
/* not evidence publication of this program. */
/* */
/* NEC Corporation accepts no responsibility for any damages */
/* resulting from the use of this sample code. */
/* This sample code is provided "AS IS", and its user assume all */
/* risks when using it. */
/* */
/*---------------------------------------------------------------*/
//#include "stdafx.h"
#include "misc.h"
/*--------------------------------------------------------------------
*
* PrintErrorCode
*
*--------------------------------------------------------------------*/
void PrintErrorCode(
BioAPI_RETURN bioReturn /* INPUT : BioAPI Error Code */
)
{
TCHAR szMessage[_MAX_PATH];
// ID Input Error
if (bioReturn == ERRCODE_ID_INPUT_ERROR)
{
wsprintf(szMessage, MESS_ID_INPUT_ERROR);
MessageBox(GetActiveWindow(), szMessage, MESS_BIOAPI_ERROR, MB_OK | MB_ICONSTOP);
}
// Not Enrolled Error
else if (bioReturn == ERRCODE_NOT_ENROLLED)
{
wsprintf(szMessage, MESS_NOT_ENROLLED);
MessageBox(GetActiveWindow(), szMessage, MESS_BIOAPI_ERROR, MB_OK | MB_ICONSTOP);
}
// BioAPI Error
else
{
wsprintf(szMessage, MESS_BIOAPI_ERROR_CODE, bioReturn);
MessageBox(GetActiveWindow(), szMessage, MESS_BIOAPI_ERROR, MB_OK | MB_ICONSTOP);
}
return;
}
/*--------------------------------------------------------------------
*
* LoadBSP
*
*--------------------------------------------------------------------*/
void LoadBSP(
BioAPI_HANDLE_PTR gModuleHandle /* INPUT : BSP Module Handle */
)
{
BioAPI_VERSION bioVersion;
bioVersion.Major = BioAPI_MAJOR;
bioVersion.Minor = BioAPI_MINOR;
bioReturn = BioAPI_Init(&bioVersion, 0, NULL, 0, NULL);
if (BioAPI_OK != bioReturn)
{
PrintErrorCode(bioReturn);
return;
}
bioReturn = BioAPI_ModuleLoad(&BSPUuid, 0, NULL, 0);
if (BioAPI_OK != bioReturn)
{
PrintErrorCode(bioReturn);
return;
}
bioReturn = BioAPI_ModuleAttach(&BSPUuid, &bioVersion, &BioAPIWinMemoryFuncs, 0, 0, 0, 0, NULL, 0, NULL, gModuleHandle);
if (BioAPI_OK != bioReturn)
{
PrintErrorCode(bioReturn);
return;
}
return;
}
/*--------------------------------------------------------------------
*
* ReleaseBSP
*
*--------------------------------------------------------------------*/
void ReleaseBSP(
BioAPI_HANDLE_PTR gModuleHandle /* INPUT : BSP Module Handle */
)
{
if (gModuleHandle != 0)
{
bioReturn = BioAPI_ModuleDetach(*gModuleHandle);
if (BioAPI_OK != bioReturn)
{
PrintErrorCode(bioReturn);
return;
}
gModuleHandle = 0;
}
bioReturn = BioAPI_ModuleUnload(&BSPUuid, NULL, 0);
if (BioAPI_OK != bioReturn)
{
PrintErrorCode(bioReturn);
return;
}
bioReturn = BioAPI_Terminate();
if (BioAPI_OK != bioReturn)
{
PrintErrorCode(bioReturn);
return;
}
return;
}
/*--------------------------------------------------------------------
*
* OutputToFile
*
*--------------------------------------------------------------------*/
BioAPI_RETURN OutputToFile(
BioAPI_HANDLE gModuleHandle, /* INPUT : BSP Module Handle */
LPTSTR lptszUserName, /* INPUT : Save File Neme */
BioAPI_BIR_HANDLE BirHandle /* INPUT : Save BIR Data */
)
{
TCHAR szFileName[_MAX_PATH];
HANDLE hFile;
DWORD dwBytesToWrite, dwBytesWritten;
BioAPI_BIR_PTR birData = NULL;
BioAPI_RETURN bioReturn;
uint32 count = 0;
struct stat buff;
// Retrieve the BIR from the BSP
bioReturn = BioAPI_GetBIRFromHandle(gModuleHandle, BirHandle, &birData);
if (bioReturn != BioAPI_OK)
{
return bioReturn;
}
// Search Save FileName
_mkdir(PATH_ENROLLED_DIRECTORY);
while (1)
{
if (++count > MaxEnrollNum)
{
return -1; // Can't make file
}
wsprintf(szFileName, PATH_ENROLLED_NAME, lptszUserName, count);
if ((stat(szFileName, &buff) != 0))
{
break;
}
}
// Open the file
hFile = CreateFile(szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return 0; // this return value is ignored anyway
}
// Write the header
WriteFile(hFile, &(birData->Header), sizeof(BioAPI_BIR_HEADER), &dwBytesWritten, NULL);
// Write the biometric data
dwBytesToWrite = LocalEndian4(birData->Header.Length) - sizeof(BioAPI_BIR_HEADER);
WriteFile(hFile, birData->BiometricData, dwBytesToWrite, &dwBytesWritten, NULL);
// Write the signature if present
if (birData->Signature)
{
WriteFile(hFile, &(birData->Signature->Length), 4, &dwBytesWritten, NULL);
dwBytesToWrite = LocalEndian4(birData->Signature->Length);
WriteFile(hFile, birData->Signature->Data, dwBytesToWrite, &dwBytesWritten, NULL);
}
// Close the file
CloseHandle(hFile);
// Free all the memory allocated for the BIR
if (birData != NULL) {
GlobalFree(birData->BiometricData);
if (birData->Signature)
{
GlobalFree(birData->Signature->Data);
GlobalFree(birData->Signature);
}
GlobalFree(birData);
}
return BioAPI_OK;
}
/*--------------------------------------------------------------------
*
* InputFromFile
*
*--------------------------------------------------------------------*/
BioAPI_RETURN InputFromFile(
LPTSTR lptszUserName, /* INPUT : Load File Name */
BioAPI_INPUT_BIR * InputBir, /* OUTPUT : Load BIR Data */
uint32 count /* INPUT : User Enroll Number */
)
{
TCHAR szFileName[_MAX_PATH];
HANDLE hFile;
DWORD dwBytesToRead, dwBytesRead;
BioAPI_BIR *bir;
// Open the file
wsprintf(szFileName, PATH_ENROLLED_NAME, lptszUserName, count);
hFile = CreateFile(szFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return BioAPIERR_BSP_RECORD_NOT_FOUND; // Return this BSP error if the file isn't present
}
// Read the header in, to determine the size
dwBytesToRead = sizeof(BioAPI_BIR_HEADER);
bir = (BioAPI_BIR*)GlobalAlloc(GPTR, sizeof(BioAPI_BIR));
if (!bir)
{
return !BioAPI_OK;
}
ReadFile(hFile, &(bir->Header), dwBytesToRead, &dwBytesRead, NULL);
// Read the biometric data
dwBytesToRead = LocalEndian4(bir->Header.Length) - sizeof(BioAPI_BIR_HEADER);
bir->BiometricData = (BioAPI_BIR_BIOMETRIC_DATA_PTR)GlobalAlloc(GPTR, dwBytesToRead);
if (!bir->BiometricData)
{
return !BioAPI_OK;
}
ReadFile(hFile, bir->BiometricData, dwBytesToRead, &dwBytesRead, NULL);
// Read the signature if present
dwBytesToRead = 0;
if (ReadFile(hFile, &dwBytesToRead, 4, &dwBytesRead, NULL) != 0 && dwBytesToRead != 0)
{
bir->Signature = (BioAPI_DATA_PTR)GlobalAlloc(GPTR, sizeof(BioAPI_DATA));
if (!bir->Signature)
{
return !BioAPI_OK;
}
bir->Signature->Length = dwBytesToRead;
dwBytesToRead = LocalEndian4(dwBytesToRead);
bir->Signature->Data = (uint8 *)GlobalAlloc(GPTR, dwBytesToRead);
if (!bir->Signature->Data)
{
return !BioAPI_OK;
}
ReadFile(hFile, bir->Signature->Data, dwBytesToRead, &dwBytesRead, NULL);
}
// Close the file
CloseHandle(hFile);
// Set up the return values
InputBir->InputBIR.BIR = bir;
InputBir->Form = BioAPI_FULLBIR_INPUT;
return BioAPI_OK;
}
/*--------------------------------------------------------------------
*
* End of misc.cpp
*
*--------------------------------------------------------------------*/
Errors:
1>libucrt.lib(exit.obj) : error LNK2005: _cexit already defined in ucrtd.lib(ucrtbased.dll)
1>libucrt.lib(onexit.obj) : error LNK2005: _crt_at_quick_exit already defined in ucrtd.lib(ucrtbased.dll)
1>libucrt.lib(onexit.obj) : error LNK2005: _crt_atexit already defined in ucrtd.lib(ucrtbased.dll)
1>libucrt.lib(onexit.obj) : error LNK2005: _execute_onexit_table already defined in ucrtd.lib(ucrtbased.dll)
1>libucrt.lib(onexit.obj) : error LNK2005: _initialize_onexit_table already defined in ucrtd.lib(ucrtbased.dll)
1>libucrt.lib(onexit.obj) : error LNK2005: _register_onexit_function already defined in ucrtd.lib(ucrtbased.dll)
1>libucrt.lib(environment_initialization.obj) : error LNK2005: _initialize_narrow_environment already defined in ucrtd.lib(ucrtbased.dll)
1>libucrt.lib(exception_filter.obj) : error LNK2005: _seh_filter_dll already defined in ucrtd.lib(ucrtbased.dll)
1>LINK : warning LNK4098: defaultlib 'MSVCRTD' conflicts with use of other libs; use /NODEFAULTLIB:library
1>LINK : warning LNK4098: defaultlib 'ucrtd.lib' conflicts with use of other libs; use /NODEFAULTLIB:library
1>C:\Users\Laptop-attendance\source\repos\Bioapitest\x64\Debug\Bioapitest.exe : fatal error LNK1169: one or more multiply defined symbols found
I have a password filter dll which, for now at least, is simply going to write to a log the username and the password when a user account's password is successfully changed. I'm coming up to some age-old problems with c-strings.
The two variables I'm interested in are of the type PUNICODE_STRING (which is simply a *UNICODE_STRING). Naturally I search the web for this data type which landed me here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa380518(v=vs.85).aspx
Give that information I know that I can access the length of this animal and that it has a pointer to a wide-character string. Awesome. That is plenty of knowledge to extract the contents I'll need (so I thought).
Here is my dll code (dllmain.cpp)
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include <iostream>
#define LOGFILE "c:\\PasswordFilter.txt"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
void WriteToLog (const wchar_t* UserName, const wchar_t* NewPassword)
{
#ifdef LOGFILE
FILE* log = fopen(LOGFILE, "a");
if(NULL == log)
{
return;
}
fwprintf(log,L"%s password was successfully reset to %s\r\n",UserName,NewPassword);
fclose(log);
#endif
return;
}
LPWSTR __stdcall ConvertWideChar(PUNICODE_STRING input)
{
wchar_t* wszString = new wchar_t[input->Length + 1];
memset(wszString, 0, sizeof(wchar_t) * (input->Length + 1));
wcsncpy(wszString,input->Buffer,input->Length);
#ifdef LOGFILE
FILE* log = fopen(LOGFILE, "a");
if(NULL != log)
{
fwprintf(log,L"value of wszString: %s\r\n",wszString);
fclose(log);
}
#endif
return wszString;
}
BOOLEAN __stdcall InitializeChangeNotify(void)
{
return TRUE;
}
NTSTATUS __stdcall PasswordChangeNotify(
PUNICODE_STRING UserName,
ULONG RelativeId,
PUNICODE_STRING NewPassword
)
{
LPWSTR ConvertedUserName = ConvertWideChar(UserName);
LPWSTR ConvertedNewPassword = ConvertWideChar(NewPassword);
WriteToLog(ConvertedUserName,ConvertedNewPassword);
return 0;
}
BOOLEAN __stdcall PasswordFilter(
PUNICODE_STRING AccountName,
PUNICODE_STRING FullName,
PUNICODE_STRING Password,
BOOLEAN SetOperation
)
{
return TRUE;
}
And here is the contents of the header file (stdafx.h)
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <stdio.h>
#include <windows.h>
#include <winnt.h>
#include <NTSecAPI.h>
// TODO: reference additional headers your program requires here
Naturally my concern is to retain accuracy. And this is where my pain begins. We have a wchar_t which communicated to me that this is likely in unicode with a UTF16 format (like all other windows based strings). The code above copies the PUNICODE_STRING's buffer to a zero-terminated wchar_t (since the buffer isn't guaranteed to be zero terminated itself) and then attempts to output that string to a log file.
I first attempted to use WideCharToMultiByte as a way to copy the buffer to a character string but that never seemed to work. The result would be null each and every time. This also ran the issue of translating unicode values to a simpler format which runs the risk of data loss. So I decided to go with what I have there for now, but the logged values have ?'s and other garbage after them, which is likely a unicode problem.
I would REALLY like to retain the unicode encoding type of this data structure if possible. How can I do so and print my values to a log?
You are not using the UNICODE_STRING::Length field correctly. It is expressed in bytes, not in characters. So you are not allocating+filling your null-terminated buffers correctly. You are also leaking the buffers you allocate.
You don't need to allocate the buffers at all. You can pass the original Buffer and Length values directly to fwprintf, no null terminators needed:
NTSTATUS __stdcall PasswordChangeNotify(
PUNICODE_STRING UserName,
ULONG RelativeId,
PUNICODE_STRING NewPassword
)
{
#ifdef LOGFILE
FILE* log = fopen(LOGFILE, "a");
if (NULL != log)
{
fwprintf(log, L"%.*s password was successfully reset to %.*s\r\n",
UserName->Length / sizeof(WCHAR), UserName->Buffer,
NewPassword->Length / sizeof(WCHAR), NewPassword->Buffer);
fclose(log);
}
#endif
return 0;
}
If you really need to add null terminators, use std::wstring instead of allocating+copying manually:
#include <string>
NTSTATUS __stdcall PasswordChangeNotify(
PUNICODE_STRING UserName,
ULONG RelativeId,
PUNICODE_STRING NewPassword
)
{
#ifdef LOGFILE
FILE* log = fopen(LOGFILE, "a");
if (NULL != log)
{
fwprintf(log, L"%.s password was successfully reset to %.s\r\n",
std::wstring(UserName->Buffer, UserName->Length / sizeof(WCHAR)).c_str(),
std::wstring(NewPassword->Buffer, NewPassword->Length / sizeof(WCHAR)).c_str());
fclose(log);
}
#endif
return 0;
}
You can actually print a UNICODE_STRING structure using the modifier %wZ with printf. No need for any fancy Buffer translations or worrying about null terminators.
UNICODE_STRING someStr;
RtlInitUnicodeString(&someStr, L"Hello");
printf("String: %wZ\n", &someStr);
fini.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
Hi I've converted VC++6 project to VC++ 2010 and I keep encountering error while displaying modal Open File dialog.
It shows bottom part of dialog but top is missing, also filter also is not populated.
header has public members for storing file information:
CString m_strFilePathName;
CString m_strFileExtName;
My code to show dialog:
static TCHAR BASED_CODE szFilter[] = _T("Open Bin File(*.abs)|")
_T("Default DataBase File(*.ddf)|")
_T("SatCodex File(*.sdx)|")
_T("Format Text File(*.txt)");
// TODO: Add your command handler code here
CFileDlg fd(TRUE, NULL, "", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter);
//"Open Bin File(*.abs)|Default DataBase File(*.ddf)|SatCodex File(*.sdx)|Format Text File(*.txt)");
const int c_cMaxFiles = 1;
const int c_cbBuffSize = (c_cMaxFiles * (MAX_PATH + 1)) + 1;
fd.GetOFN().lpstrFile = m_strFilePathName.GetBuffer(c_cbBuffSize);
fd.GetOFN().nMaxFile = c_cbBuffSize;
// Dialog hangs on this line:
if(fd.DoModal() != IDOK) return;
Diagnostic returns: First-chance exception at 0x006c69cc in AliEditor.exe: 0xC0000005: Access violation reading location 0x00000020.
Breaking while in hanging mode call stack returns this information:
user32.dll!_NtUserWaitMessage#0() + 0x15 bytes <-STOPPED HERE
user32.dll!_NtUserWaitMessage#0() + 0x15 bytes
user32.dll!_DialogBox2#16() + 0x109 bytes
user32.dll!_InternalDialogBox#24() + 0xc9 bytes
user32.dll!_DialogBoxIndirectParamAorW#24() + 0x36 bytes
user32.dll!_DialogBoxIndirectParamW#20() + 0x1b bytes
comdlg32.dll!CFileOpenSave::Show() + 0x146 bytes
AliEditor.exe!CFileDialog::DoModal() Line 748 + 0x26 bytes C++
AliEditor.exe!CMainFrame::OnFileOpen() Line 195 + 0xb bytes C++
AliEditor.exe!_AfxDispatchCmdMsg(CCmdTarget * pTarget, unsigned int nID, int nCode, void (void)* pfn, void * pExtra, unsigned int nSig, AFX_CMDHANDLERINFO * pHandlerInfo) Line 82 C++
AliEditor.exe!CCmdTarget::OnCmdMsg(unsigned int nID, int nCode, void * pExtra, AFX_CMDHANDLERINFO * pHandlerInfo) Line 381 + 0x27 bytes C++
AliEditor.exe!CFrameWnd::OnCmdMsg(unsigned int nID, int nCode, void * pExtra, AFX_CMDHANDLERINFO * pHandlerInfo) Line 973 + 0x18 bytes C++
AliEditor.exe!CWnd::OnCommand(unsigned int wParam, long lParam) Line 2729 C++
AliEditor.exe!CFrameWnd::OnCommand(unsigned int wParam, long lParam) Line 371 C++
AliEditor.exe!CWnd::OnWndMsg(unsigned int message, unsigned int wParam, long lParam, long * pResult) Line 2101 + 0x1e bytes C++
AliEditor.exe!CWnd::WindowProc(unsigned int message, unsigned int wParam, long lParam) Line 2087 + 0x20 bytes C++
AliEditor.exe!AfxCallWndProc(CWnd * pWnd, HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 257 + 0x1c bytes C++
AliEditor.exe!AfxWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 420 C++
Declarations of I guess (I am not C++ developer) overriding (fileDlg.cpp):
#include "stdafx.h"
#include "AliEditor.h"
#include "FileDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CFileDlg
IMPLEMENT_DYNAMIC(CFileDlg, CFileDialog)
CFileDlg::CFileDlg(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName,
DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) :
CFileExportDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd)
{
}
BEGIN_MESSAGE_MAP(CFileDlg, CFileExportDialog)
//{{AFX_MSG_MAP(CFileDlg)
ON_WM_CLOSE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
File "dlgfile.cpp" is very big, but this just the top part:
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#include <dlgs.h> // for standard control IDs for commdlg
#include "afxglobals.h"
#define new DEBUG_NEW
////////////////////////////////////////////////////////////////////////////
// FileOpen/FileSaveAs common dialog helper
CFileDialog::CFileDialog(BOOL bOpenFileDialog,
LPCTSTR lpszDefExt, LPCTSTR lpszFileName, DWORD dwFlags,
LPCTSTR lpszFilter, CWnd* pParentWnd, DWORD dwSize, BOOL bVistaStyle)
: CCommonDialog(pParentWnd)
{
OSVERSIONINFO vi;
ZeroMemory(&vi, sizeof(OSVERSIONINFO));
vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
::GetVersionEx(&vi);
// if running under Vista
if (vi.dwMajorVersion >= 6)
{
m_bVistaStyle = bVistaStyle;
}
else
{
m_bVistaStyle = FALSE;
}
m_bPickFoldersMode = FALSE;
// determine size of OPENFILENAME struct if dwSize is zero
if (dwSize == 0)
{
dwSize = sizeof(OPENFILENAME);
}
// size of OPENFILENAME must be at least version 5
ASSERT(dwSize >= sizeof(OPENFILENAME));
// allocate memory for OPENFILENAME struct based on size passed in
m_pOFN = static_cast<LPOPENFILENAME>(malloc(dwSize));
ASSERT(m_pOFN != NULL);
if (m_pOFN == NULL)
AfxThrowMemoryException();
memset(&m_ofn, 0, dwSize); // initialize structure to 0/NULL
m_szFileName[0] = '\0';
m_szFileTitle[0] = '\0';
m_pofnTemp = NULL;
m_bOpenFileDialog = bOpenFileDialog;
m_nIDHelp = bOpenFileDialog ? AFX_IDD_FILEOPEN : AFX_IDD_FILESAVE;
m_ofn.lStructSize = dwSize;
m_ofn.lpstrFile = m_szFileName;
m_ofn.nMaxFile = _countof(m_szFileName);
m_ofn.lpstrDefExt = lpszDefExt;
m_ofn.lpstrFileTitle = (LPTSTR)m_szFileTitle;
m_ofn.nMaxFileTitle = _countof(m_szFileTitle);
m_ofn.Flags |= dwFlags | OFN_ENABLEHOOK | OFN_EXPLORER;
if(dwFlags & OFN_ENABLETEMPLATE)
m_ofn.Flags &= ~OFN_ENABLESIZING;
m_ofn.hInstance = AfxGetResourceHandle();
m_ofn.lpfnHook = (COMMDLGPROC)_AfxCommDlgProc;
// setup initial file name
if (lpszFileName != NULL)
Checked::tcsncpy_s(m_szFileName, _countof(m_szFileName), lpszFileName, _TRUNCATE);
// Translate filter into commdlg format (lots of \0)
if (lpszFilter != NULL)
{
m_strFilter = lpszFilter;
LPTSTR pch = m_strFilter.GetBuffer(0); // modify the buffer in place
// MFC delimits with '|' not '\0'
while ((pch = _tcschr(pch, '|')) != NULL)
*pch++ = '\0';
m_ofn.lpstrFilter = m_strFilter;
// do not call ReleaseBuffer() since the string contains '\0' characters
}
if (m_bVistaStyle == TRUE)
{
if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)))
{ // multi-threaded is not supported
IFileDialog* pIFileDialog;
IFileDialogCustomize* pIFileDialogCustomize;
HRESULT hr;
USE_INTERFACE_PART_STD(FileDialogEvents);
USE_INTERFACE_PART_STD(FileDialogControlEvents);
if (m_bOpenFileDialog)
{
hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pIFileDialog));
}
else
{
hr = CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pIFileDialog));
}
if (FAILED(hr))
{
m_bVistaStyle = FALSE;
return;
}
hr = pIFileDialog->QueryInterface(IID_PPV_ARGS(&pIFileDialogCustomize));
ENSURE(SUCCEEDED(hr));
hr = pIFileDialog->Advise(reinterpret_cast<IFileDialogEvents*>(&m_xFileDialogEvents), &m_dwCookie);
ENSURE(SUCCEEDED(hr));
m_pIFileDialog = static_cast<void*>(pIFileDialog);
m_pIFileDialogCustomize = static_cast<void*>(pIFileDialogCustomize);
}
else
{
m_bVistaStyle = FALSE;
}
}
}
CFileDialog::~CFileDialog()
{
free(m_pOFN);
if (m_bVistaStyle == TRUE)
{
HRESULT hr;
hr = (static_cast<IFileDialog*>(m_pIFileDialog))->Unadvise(m_dwCookie);
ENSURE(SUCCEEDED(hr));
(static_cast<IFileDialogCustomize*>(m_pIFileDialogCustomize))->Release();
(static_cast<IFileDialog*>(m_pIFileDialog))->Release();
CoUninitialize();
}
}
const OPENFILENAME& CFileDialog::GetOFN() const
{
return *m_pOFN;
}
OPENFILENAME& CFileDialog::GetOFN()
{
return *m_pOFN;
}
Going step by step I get to this point in same ("dlgfile.cpp") file:
INT_PTR CFileDialog::DoModal()
{
ASSERT_VALID(this);
ASSERT(m_ofn.Flags & OFN_ENABLEHOOK);
ASSERT(m_ofn.lpfnHook != NULL); // can still be a user hook
// zero out the file buffer for consistent parsing later
ASSERT(AfxIsValidAddress(m_ofn.lpstrFile, m_ofn.nMaxFile));
DWORD nOffset = lstrlen(m_ofn.lpstrFile)+1;
ASSERT(nOffset <= m_ofn.nMaxFile);
memset(m_ofn.lpstrFile+nOffset, 0, (m_ofn.nMaxFile-nOffset)*sizeof(TCHAR));
// This is a special case for the file open/save dialog,
// which sometimes pumps while it is coming up but before it has
// disabled the main window.
HWND hWndFocus = ::GetFocus();
BOOL bEnableParent = FALSE;
m_ofn.hwndOwner = PreModal();
AfxUnhookWindowCreate();
if (m_ofn.hwndOwner != NULL && ::IsWindowEnabled(m_ofn.hwndOwner))
{
bEnableParent = TRUE;
::EnableWindow(m_ofn.hwndOwner, FALSE);
}
_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
ASSERT(pThreadState->m_pAlternateWndInit == NULL);
if (m_bVistaStyle == TRUE)
{
AfxHookWindowCreate(this);
}
else if (m_ofn.Flags & OFN_EXPLORER)
pThreadState->m_pAlternateWndInit = this;
else
AfxHookWindowCreate(this);
INT_PTR nResult = 0;
if (m_bVistaStyle == TRUE)
{
ApplyOFNToShellDialog();
// HERE CALLS **OPENFILENAME& CFileDialog::GetOFN()** method and then hangs
HRESULT hr = (static_cast<IFileDialog*>(m_pIFileDialog))->Show(m_ofn.hwndOwner);
nResult = (hr == S_OK) ? IDOK : IDCANCEL;
}
else if (m_bOpenFileDialog)
nResult = ::AfxCtxGetOpenFileName(&m_ofn);
else
nResult = ::AfxCtxGetSaveFileName(&m_ofn);
if (nResult)
ASSERT(pThreadState->m_pAlternateWndInit == NULL);
pThreadState->m_pAlternateWndInit = NULL;
// Second part of special case for file open/save dialog.
if (bEnableParent)
::EnableWindow(m_ofn.hwndOwner, TRUE);
if (::IsWindow(hWndFocus))
::SetFocus(hWndFocus);
PostModal();
return nResult ? nResult : IDCANCEL;
}
Could anyone help me?
[Update]
As no one can help me at this stage, I've uploaded project to public place here. Can anyone download and tell me what's wrong when I click open file?
The only problem that I can see is that your filter string looks incorrect. It looks like your code is based on one of the MSDN samples. And according to that sample your szFilter should look like this:
static TCHAR BASED_CODE szFilter[] = _T("Open Bin File(*.abs)|*.abs|")
_T("Default DataBase File(*.ddf)|*.ddf|")
_T("SatCodex File(*.sdx)|*.sdx|")
_T("Format Text File(*.txt)|*.txt||");
FYI I used http://msdn.microsoft.com/en-US/library/wh5hz49d(v=vs.100).aspx as a reference.
[update]
I created a small MFC app and pasted in your code. There is a typo in your code sample. The class is CFileDialog, not CFileDlg. I fixed it, then applied the change described above to fix the szFilter String. It works for me. The file dialog displays, I enter some data and dismiss the file dialog. No access violation, no assert. I think you need to look elsewhere in your code to track down the problem.
[update 2]
Ignore everything I previously said. Your original access violation is around line 174 of FileExportDialog.cpp
void CFileExportDialog::OnTypeChange()
{
// get current filename
CWnd *fileNameBox = GetParent()->GetDlgItem(edt1);
ASSERT_VALID(fileNameBox);
CString fileName; fileNameBox->GetWindowText(fileName);
// get current extension
CWnd *typeNameBox = GetParent()->GetDlgItem(cmb1);
ASSERT_VALID(typeNameBox);
CString typeName; typeNameBox->GetWindowText(typeName);
...
The real call stack is:
AliEditor.exe!CWnd::GetDlgItem(int nID) Line 92 + 0x3 bytes C++
AliEditor.exe!CFileExportDialog::OnTypeChange() Line 177 + 0x14 bytes C++
AliEditor.exe!CFileDialog::XFileDialogEvents::OnTypeChange(IFileDialog * __formal) Line 619 C++
comdlg32.dll!76138057()
[Frames below may be incorrect and/or missing, no symbols loaded for comdlg32.dll]
comctl32.dll!731c7613()
comdlg32.dll!7612bdda()
comdlg32.dll!7612c5a0()
KernelBase.dll!76096055()
comctl32.dll!7458b575()
user32.dll!767281c8()
user32.dll!76728326()
user32.dll!76728347()
user32.dll!76730d27()
user32.dll!7673794a()
AliEditor.exe!_AfxActivationWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 456 + 0x1a bytes C++
user32.dll!767262fa()
user32.dll!76726d3a()
user32.dll!76726ce9()
user32.dll!7672965e()
user32.dll!7675206f()
user32.dll!7674cf4b()
user32.dll!7674ce8a()
user32.dll!7674cc0e()
comdlg32.dll!7612597b()
AliEditor.exe!CFileDialog::DoModal() Line 748 + 0x26 bytes C++
...
The program is crashing at CWnd::GetDlgItem because the CWnd "this" pointer is 0. This is because the first line of CFileExportDialog::OnTypeChange is GetParent() which is NULL because this dialog has no parent.
The class CFileExportDialog is not part of Visual Studio it appears to be based on some public domain code written in 1999 from http://www.codeguru.com/cpp/w-d/dislog/commondialogs/article.php/c1863/CFileExportDialog-Class.htm. And it looks like the implementation of OnTypeChange is based on the original developer reverse engineering the details of the Microsoft CFileDialog class as it was implemented in 1999. I'm guessing that the internals have changed in VS 2010 so that class is not longer useful.
Next time you run the program, set a breakpoint at line 177 of FileExportDialog.cpp. When you hit the breakpoint, single-step through the code and watch the crashes and asserts as the obsolete code attempts to do things it should never have been doing in the first place.
Recommend you dump the CFileExportDialog class and rewrite your program using the standard MFC CFileDialog class.
Given a handle to a Windows Registry Key, such as the ones that are set by ::RegOpenKeyEx(), is it possible to determine the full path to that key?
I realize that in a simple application all you have to do is look up 5 or 10 lines and read... but in a complex app like the one I'm debugging, the key I'm interested in can be opened from a series of calls.
Use LoadLibrary and NtQueryKey exported function as in the following code snippet.
#include <windows.h>
#include <string>
typedef LONG NTSTATUS;
#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#endif
#ifndef STATUS_BUFFER_TOO_SMALL
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
#endif
std::wstring GetKeyPathFromKKEY(HKEY key)
{
std::wstring keyPath;
if (key != NULL)
{
HMODULE dll = LoadLibrary(L"ntdll.dll");
if (dll != NULL) {
typedef DWORD (__stdcall *NtQueryKeyType)(
HANDLE KeyHandle,
int KeyInformationClass,
PVOID KeyInformation,
ULONG Length,
PULONG ResultLength);
NtQueryKeyType func = reinterpret_cast<NtQueryKeyType>(::GetProcAddress(dll, "NtQueryKey"));
if (func != NULL) {
DWORD size = 0;
DWORD result = 0;
result = func(key, 3, 0, 0, &size);
if (result == STATUS_BUFFER_TOO_SMALL)
{
size = size + 2;
wchar_t* buffer = new (std::nothrow) wchar_t[size/sizeof(wchar_t)]; // size is in bytes
if (buffer != NULL)
{
result = func(key, 3, buffer, size, &size);
if (result == STATUS_SUCCESS)
{
buffer[size / sizeof(wchar_t)] = L'\0';
keyPath = std::wstring(buffer + 2);
}
delete[] buffer;
}
}
}
FreeLibrary(dll);
}
}
return keyPath;
}
int _tmain(int argc, _TCHAR* argv[])
{
HKEY key = NULL;
LONG ret = ERROR_SUCCESS;
ret = RegOpenKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft", &key);
if (ret == ERROR_SUCCESS)
{
wprintf_s(L"Key path for %p is '%s'.", key, GetKeyPathFromKKEY(key).c_str());
RegCloseKey(key);
}
return 0;
}
This will print the key path on the console:
Key path for 00000FDC is
'\REGISTRY\MACHINE\SOFTWARE\Microsoft'.
I was excited to find this article and its well liked solution.
Until I found that my system's NTDLL.DLL did not have NtQueryKeyType.
After some hunting around, I ran across ZwQueryKey in the DDK forums.
It is in C#, but here is the solution that works for me:
enum KEY_INFORMATION_CLASS
{
KeyBasicInformation, // A KEY_BASIC_INFORMATION structure is supplied.
KeyNodeInformation, // A KEY_NODE_INFORMATION structure is supplied.
KeyFullInformation, // A KEY_FULL_INFORMATION structure is supplied.
KeyNameInformation, // A KEY_NAME_INFORMATION structure is supplied.
KeyCachedInformation, // A KEY_CACHED_INFORMATION structure is supplied.
KeyFlagsInformation, // Reserved for system use.
KeyVirtualizationInformation, // A KEY_VIRTUALIZATION_INFORMATION structure is supplied.
KeyHandleTagsInformation, // Reserved for system use.
MaxKeyInfoClass // The maximum value in this enumeration type.
}
[StructLayout(LayoutKind.Sequential)]
public struct KEY_NAME_INFORMATION
{
public UInt32 NameLength; // The size, in bytes, of the key name string in the Name array.
public char[] Name; // An array of wide characters that contains the name of the key.
// This character string is not null-terminated.
// Only the first element in this array is included in the
// KEY_NAME_INFORMATION structure definition.
// The storage for the remaining elements in the array immediately
// follows this element.
}
[DllImport("ntdll.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern int ZwQueryKey(IntPtr hKey, KEY_INFORMATION_CLASS KeyInformationClass, IntPtr lpKeyInformation, int Length, out int ResultLength);
public static String GetHKeyName(IntPtr hKey)
{
String result = String.Empty;
IntPtr pKNI = IntPtr.Zero;
int needed = 0;
int status = ZwQueryKey(hKey, KEY_INFORMATION_CLASS.KeyNameInformation, IntPtr.Zero, 0, out needed);
if ((UInt32)status == 0xC0000023) // STATUS_BUFFER_TOO_SMALL
{
pKNI = Marshal.AllocHGlobal(sizeof(UInt32) + needed + 4 /*paranoia*/);
status = ZwQueryKey(hKey, KEY_INFORMATION_CLASS.KeyNameInformation, pKNI, needed, out needed);
if (status == 0) // STATUS_SUCCESS
{
char[] bytes = new char[2 + needed + 2];
Marshal.Copy(pKNI, bytes, 0, needed);
// startIndex == 2 skips the NameLength field of the structure (2 chars == 4 bytes)
// needed/2 reduces value from bytes to chars
// needed/2 - 2 reduces length to not include the NameLength
result = new String(bytes, 2, (needed/2)-2);
}
}
Marshal.FreeHGlobal(pKNI);
return result;
}
I've only ever tried it while running as Administrator, which may be required.
The result is a bit oddly formatted: \REGISTRY\MACHINE\SOFTWARE\company\product for example, instead of HKEY_LOCAL_MACHINE\SOFTWARE\company\product.
Nominally no because it's just a handle and there is no API that I know of to let you do this in the normal Windows API's.
HOWEVER the Native API has lots of functions some of which can give you handles open for given files and the like so there maybe something similar for the Registry. That and RegMon by SysInternals may do something like this but you'll have to Google I'm afraid :/
You can use RegSaveKey and write it to a file, then look at the file.
Alternatively you can keep a global map of HKEYs to LPCWSTRs and add entries when you open them and do lookups whenever.
You may also be able to do something with the !reg command in WinDBG / NTSD, but you can't just give it the HKEY. You'll have to do some other trickery to get the info you want out of it.
Since std::wstring allows to construct string from pointer and count of characters, and the kernel string always return the count of bytes, it is not necessary to terminated the string with NUL. I do not suggest that to add size or to offset the pointer by constant number directly, it's better to use the real data type like the structure types instead, and std::vector<UCHAR> instead of new for dynamic memory allocating. I modified the code from highly upvoted answer as the followings.
The legacy way, obtaining the function pointer from ntdll.dll dynamically:
#include <ntstatus.h>
#define WIN32_NO_STATUS
#include <windows.h>
#include <winternl.h>
#include <string>
#include <vector>
#define REG_KEY_PATH_LENGTH 1024
typedef enum _KEY_INFORMATION_CLASS {
KeyBasicInformation,
KeyNodeInformation,
KeyFullInformation,
KeyNameInformation,
KeyCachedInformation,
KeyFlagsInformation,
KeyVirtualizationInformation,
KeyHandleTagsInformation,
KeyTrustInformation,
KeyLayerInformation,
MaxKeyInfoClass
} KEY_INFORMATION_CLASS;
typedef struct _KEY_NAME_INFORMATION {
ULONG NameLength;
WCHAR Name[1];
} KEY_NAME_INFORMATION, *PKEY_NAME_INFORMATION;
typedef NTSTATUS (NTAPI *PFN_NtQueryKey)(
__in HANDLE /* KeyHandle */,
__in KEY_INFORMATION_CLASS /* KeyInformationClass */,
__out_opt PVOID /* KeyInformation */,
__in ULONG /* Length */,
__out ULONG * /* ResultLength */
);
std::wstring RegQueryKeyPath(HKEY hKey)
{
std::wstring keyPath;
if (hKey != NULL)
{
HMODULE hinstDLL = GetModuleHandleW(L"ntdll.dll");
if (hinstDLL != NULL)
{
FARPROC pfn = GetProcAddress(hinstDLL, "NtQueryKey");
if (pfn != NULL)
{
NTSTATUS Status;
std::vector<UCHAR> Buffer(FIELD_OFFSET(KEY_NAME_INFORMATION, Name) + sizeof(WCHAR) * REG_KEY_PATH_LENGTH);
KEY_NAME_INFORMATION *pkni;
ULONG Length;
TryAgain:
Status = reinterpret_cast<PFN_NtQueryKey>(pfn)(hKey, KeyNameInformation, Buffer.data(), Buffer.size(), &Length);
switch (Status) {
case STATUS_BUFFER_TOO_SMALL:
case STATUS_BUFFER_OVERFLOW:
Buffer.resize(Length);
goto TryAgain;
case STATUS_SUCCESS:
pkni = reinterpret_cast<KEY_NAME_INFORMATION *>(Buffer.data());
keyPath.assign(pkni->Name, pkni->NameLength / sizeof(WCHAR));
default:
break;
}
}
}
}
return keyPath;
}
If you are using Visual Studio 2015 or above, ntdll.lib is included by default, so I suggest that linking to ntdll.dll statically:
#include <ntstatus.h>
#define WIN32_NO_STATUS
#include <windows.h>
#include <winternl.h>
#pragma comment(lib, "ntdll")
#include <string>
#include <vector>
#define REG_KEY_PATH_LENGTH 1024
typedef enum _KEY_INFORMATION_CLASS {
KeyBasicInformation,
KeyNodeInformation,
KeyFullInformation,
KeyNameInformation,
KeyCachedInformation,
KeyFlagsInformation,
KeyVirtualizationInformation,
KeyHandleTagsInformation,
KeyTrustInformation,
KeyLayerInformation,
MaxKeyInfoClass
} KEY_INFORMATION_CLASS;
typedef struct _KEY_NAME_INFORMATION {
ULONG NameLength;
WCHAR Name[1];
} KEY_NAME_INFORMATION, *PKEY_NAME_INFORMATION;
EXTERN_C NTSYSAPI NTSTATUS NTAPI NtQueryKey(
__in HANDLE /* KeyHandle */,
__in KEY_INFORMATION_CLASS /* KeyInformationClass */,
__out_opt PVOID /* KeyInformation */,
__in ULONG /* Length */,
__out ULONG * /* ResultLength */
);
std::wstring RegQueryKeyPath(HKEY hKey)
{
std::wstring keyPath;
NTSTATUS Status;
std::vector<UCHAR> Buffer(FIELD_OFFSET(KEY_NAME_INFORMATION, Name) + sizeof(WCHAR) * REG_KEY_PATH_LENGTH);
KEY_NAME_INFORMATION *pkni;
ULONG Length;
TryAgain:
Status = NtQueryKey(hKey, KeyNameInformation, Buffer.data(), Buffer.size(), &Length);
switch (Status) {
case STATUS_BUFFER_TOO_SMALL:
case STATUS_BUFFER_OVERFLOW:
Buffer.resize(Length);
goto TryAgain;
case STATUS_SUCCESS:
pkni = reinterpret_cast<KEY_NAME_INFORMATION *>(Buffer.data());
keyPath.assign(pkni->Name, pkni->NameLength / sizeof(WCHAR));
default:
break;
}
return keyPath;
}
Note that NtQueryKey returned STATUS_BUFFER_OVERFLOW but not STATUS_BUFFER_TOO_SMALL on Windows 10 if the supplied buffer is insufficient.
For ntsd/windbg:
!handle yourhandle 4