EDN Admin
Well-known member
I built an application with VS 2010 (VC 10, win32 native) for Windows 7 and I encountered the following problem:
when an application code contains:
#pragma comment(lib, "Netapi32.lib"); calls to the CoInitializeEx/CoInitialize and CoUninitialize functions; calls to the DsGetDcName function from the netapi32.dll,
it fails to start with this error: "The application was unable to start correctly (0xc0000005). Click OK to close the application."
Steps to reproduce the issue (detailed description of the problem) <span style="text-decoration:underline
under Windows 7 Ultimate N x64:
<ol>
Create a new "Win32 Console Application" with VS 2010 "New Project" dialog. Name it "pragmlib".
Open the "pragmlib.cpp" (cpp file with the main) and replace it content with this one:<br/>
<div style="background-color:white; color:black
<pre lang="x-cpp #include <Windows.h>
#include <Dsgetdc.h>
#include <iostream>
#include <tchar.h>
#if !defined(NTDDI_VERSION)
#define NTDDI_VERSION = NTDDI_WIN7
#endif
#if !defined(_WIN32_WINNT)
#define _WIN32_WINNT = _WIN32_WINNT_WIN7
#endif
#if !defined(WINVER)
#define WINVER = 0x0601
#endif
#define SAMPLE_DOMAIN (TEXT("sample.com"))
/*
* CL controlling defines.
*/
#define USE_PRAGMA_COMMENT_LIB
#define ENABLED_COINITIALIZE_CALLS
#if defined(USE_PRAGMA_COMMENT_LIB)
#pragma comment(lib, "Netapi32.lib")
#else
typedef DWORD (WINAPI *DsGetDcNameFunc)(_In_opt_ LPCTSTR,
_In_opt_ LPCTSTR,
_In_opt_ GUID*,
_In_opt_ LPCTSTR,
_In_ ULONG,
_Out_ PDOMAIN_CONTROLLER_INFO*);
#endif
int _tmain(int argc, _TCHAR* argv[])
{
#if defined(ENABLED_COINITIALIZE_CALLS)
HRESULT hCOMInitializationResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if ((hCOMInitializationResult != S_OK) && (hCOMInitializationResult != S_FALSE))
{
return -1;
}
#endif
ULONG nDCLocatorFlags = DS_DIRECTORY_SERVICE_REQUIRED | DS_IS_DNS_NAME | DS_RETURN_DNS_NAME;
PDOMAIN_CONTROLLER_INFO pDCInfo;
DWORD nDCLocatorResult = ERROR_INVALID_FUNCTION; // Just as a stub.
#if defined(USE_PRAGMA_COMMENT_LIB)
nDCLocatorResult = DsGetDcName(NULL,
SAMPLE_DOMAIN,
NULL,
NULL,
nDCLocatorFlags,
&pDCInfo);
#else
HMODULE hNetAPI32 = LoadLibraryEx(TEXT("netapi32.dll"), NULL, 0);
if (hNetAPI32)
{
DsGetDcNameFunc pDsGetDcName =
#if defined(_UNICODE)
reinterpret_cast<DsGetDcNameFunc> (GetProcAddress(hNetAPI32, "DsGetDcNameW"));
#else
reinterpret_cast<DsGetDcNameFunc> (GetProcAddress(hNetAPI32, "DsGetDcNameA"));
#endif
if (pDsGetDcName != nullptr)
{
nDCLocatorResult = (pDsGetDcName)(NULL, SAMPLE_DOMAIN, NULL, NULL, nDCLocatorFlags, &pDCInfo);
}
FreeLibrary(hNetAPI32);
}
#endif
if (nDCLocatorResult == ERROR_SUCCESS)
{
std::wcout << pDCInfo->DomainControllerName << std::endl;
}
else
{
std::wcout << TEXT("DsGetDcName failed.") << std::endl;
}
#if defined(ENABLED_COINITIALIZE_CALLS)
CoUninitialize();
#endif
_getwchar_nolock();
return 0;
}
[/code]
<br/>
The sample allows switching between how-to-link-the-netapi32.dll. When the USE_PRAGMA_COMMENT_LIB macro is defined, code will contain the line "#pragma comment(lib, "Netapi32.lib")". Otherwise the application will make run-time linking with the netapi32.dll.
You can also use the ENABLED_COINITIALIZE_CALLS macro to enable/disable calls to CoInitializeEx and CoUninitialize functions.
Define both the USE_PRAGMA_COMMENT_LIB and the ENABLED_COINITIALIZE_CALLS macros. This allows calls to CoInitializeEx/CoIninitialize and CoUninitialize functions and makes static link with the netapi32.dll.
Rebuild the project and run it. Application should fail to start.
Undefine the ENABLED_COINITIALIZE_CALLS. If youâll build the project and try to start the app, it would fail. But if youâll
rebuild the project, application will start correctly. If you undefine the USE_PRAGMA_COMMENT_LIB, application will make run-time link to the dll. In such "configuration" application always works well.
</ol>
It should be noted that this issue is specific to "Win32" solution/project platform (IA-32) â both "Debug" and "Release" configurations. Under "x64" platform the issue doesnt appear â application starts and works well (note: "x64" project configuration
was built with <span style="text-decoration:underline native x64 toolset, not with cross-platform one). Moreover, this problem appears only when an application is trying to start under Windows Seven Ultimate
N x64 (ENU) (for example, the same code works fine with Windows Seven Ultimate x64 (RUS) (without N index, with Media Player)). On OSes for 80x86 the problem doesnât appear.
So, let me emphasize the key moment: when the code contains the "#pragma comment(lib, "Netapi32.lib")" line, contains calls to the CoInitializeEx/CoInitialize and CoUninitialize and its built for x86 (IA-32) platform, an application fails to start
correctly under Windows Seven Ultimate N x64 (ENU). Application with the same code works fine under Windows XP Professional x86, Windows Server 2003 x86, Windows Seven Ultimate x64 (RUS), Windows Seven Ultimate N x86 (ENU) (I didnt test the
issue with Windows Vista).
By the way, if an application code doesnt use the pragma directive, but specifies the netapi32.lib as linker input (in the project property pages), the issue goes away.
I tried to create a sample that doesnt require CRT. When the project was rebuilt for "Win32" or "x64" platform, linker failed with the error: "error LNK2019: unresolved external symbol __imp__DsGetDcNameW@24 referenced in function _wmain" when I used
"#pragma comment(lib, "Netapi32.lib")". Does linker think that DsGetDcNameW is implemented in CRT libs, because the pragma directive writes something wrong into the obj file? Well, this problem is immune against Windows OS version -- it doesnt matter
what Windows hosts VS 2010 -- for "Win32" solution/project platform build always fails.
So, my question is: whats wrong? Is it my fault, or does pragma do something wrong? Or is this something else?
Tools versions (x86) and OS, where builds were made:<br/>
CL: 16.00.30319.01.<br/>
LINK: 10.00.30319.01.<br/>
RC: 6.1.7600.16385.<br/>
Windows 6.1 (build 7600): Windows 7 Ultimate N x64 ENU.
Here are the complete samples I used for this post:
<ol>
<a title="pragmlib.zip, 3.75 kB http://files.myopera.com/std-shared-ptr/files/pragmlib.zip pragmlib.zip â simple VS 2010 solution as it was made by VS "New Project" wizard (with some oversimplifying modifications).
<a title="pragmlib-nocrt.zip, 3.74 kB http://files.myopera.com/std-shared-ptr/files/pragmlib-nocrt.zip pragmlib-nocrt.zip â the same as pragmlib.zip, but project here doesnt require CRT to work (linker has /NODEFAULTLIB /ENTRY:"wmain"
switches). </ol>
View the full article
when an application code contains:
#pragma comment(lib, "Netapi32.lib"); calls to the CoInitializeEx/CoInitialize and CoUninitialize functions; calls to the DsGetDcName function from the netapi32.dll,
it fails to start with this error: "The application was unable to start correctly (0xc0000005). Click OK to close the application."
Steps to reproduce the issue (detailed description of the problem) <span style="text-decoration:underline
under Windows 7 Ultimate N x64:
<ol>
Create a new "Win32 Console Application" with VS 2010 "New Project" dialog. Name it "pragmlib".
Open the "pragmlib.cpp" (cpp file with the main) and replace it content with this one:<br/>
<div style="background-color:white; color:black
<pre lang="x-cpp #include <Windows.h>
#include <Dsgetdc.h>
#include <iostream>
#include <tchar.h>
#if !defined(NTDDI_VERSION)
#define NTDDI_VERSION = NTDDI_WIN7
#endif
#if !defined(_WIN32_WINNT)
#define _WIN32_WINNT = _WIN32_WINNT_WIN7
#endif
#if !defined(WINVER)
#define WINVER = 0x0601
#endif
#define SAMPLE_DOMAIN (TEXT("sample.com"))
/*
* CL controlling defines.
*/
#define USE_PRAGMA_COMMENT_LIB
#define ENABLED_COINITIALIZE_CALLS
#if defined(USE_PRAGMA_COMMENT_LIB)
#pragma comment(lib, "Netapi32.lib")
#else
typedef DWORD (WINAPI *DsGetDcNameFunc)(_In_opt_ LPCTSTR,
_In_opt_ LPCTSTR,
_In_opt_ GUID*,
_In_opt_ LPCTSTR,
_In_ ULONG,
_Out_ PDOMAIN_CONTROLLER_INFO*);
#endif
int _tmain(int argc, _TCHAR* argv[])
{
#if defined(ENABLED_COINITIALIZE_CALLS)
HRESULT hCOMInitializationResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if ((hCOMInitializationResult != S_OK) && (hCOMInitializationResult != S_FALSE))
{
return -1;
}
#endif
ULONG nDCLocatorFlags = DS_DIRECTORY_SERVICE_REQUIRED | DS_IS_DNS_NAME | DS_RETURN_DNS_NAME;
PDOMAIN_CONTROLLER_INFO pDCInfo;
DWORD nDCLocatorResult = ERROR_INVALID_FUNCTION; // Just as a stub.
#if defined(USE_PRAGMA_COMMENT_LIB)
nDCLocatorResult = DsGetDcName(NULL,
SAMPLE_DOMAIN,
NULL,
NULL,
nDCLocatorFlags,
&pDCInfo);
#else
HMODULE hNetAPI32 = LoadLibraryEx(TEXT("netapi32.dll"), NULL, 0);
if (hNetAPI32)
{
DsGetDcNameFunc pDsGetDcName =
#if defined(_UNICODE)
reinterpret_cast<DsGetDcNameFunc> (GetProcAddress(hNetAPI32, "DsGetDcNameW"));
#else
reinterpret_cast<DsGetDcNameFunc> (GetProcAddress(hNetAPI32, "DsGetDcNameA"));
#endif
if (pDsGetDcName != nullptr)
{
nDCLocatorResult = (pDsGetDcName)(NULL, SAMPLE_DOMAIN, NULL, NULL, nDCLocatorFlags, &pDCInfo);
}
FreeLibrary(hNetAPI32);
}
#endif
if (nDCLocatorResult == ERROR_SUCCESS)
{
std::wcout << pDCInfo->DomainControllerName << std::endl;
}
else
{
std::wcout << TEXT("DsGetDcName failed.") << std::endl;
}
#if defined(ENABLED_COINITIALIZE_CALLS)
CoUninitialize();
#endif
_getwchar_nolock();
return 0;
}
[/code]
<br/>
The sample allows switching between how-to-link-the-netapi32.dll. When the USE_PRAGMA_COMMENT_LIB macro is defined, code will contain the line "#pragma comment(lib, "Netapi32.lib")". Otherwise the application will make run-time linking with the netapi32.dll.
You can also use the ENABLED_COINITIALIZE_CALLS macro to enable/disable calls to CoInitializeEx and CoUninitialize functions.
Define both the USE_PRAGMA_COMMENT_LIB and the ENABLED_COINITIALIZE_CALLS macros. This allows calls to CoInitializeEx/CoIninitialize and CoUninitialize functions and makes static link with the netapi32.dll.
Rebuild the project and run it. Application should fail to start.
Undefine the ENABLED_COINITIALIZE_CALLS. If youâll build the project and try to start the app, it would fail. But if youâll
rebuild the project, application will start correctly. If you undefine the USE_PRAGMA_COMMENT_LIB, application will make run-time link to the dll. In such "configuration" application always works well.
</ol>
It should be noted that this issue is specific to "Win32" solution/project platform (IA-32) â both "Debug" and "Release" configurations. Under "x64" platform the issue doesnt appear â application starts and works well (note: "x64" project configuration
was built with <span style="text-decoration:underline native x64 toolset, not with cross-platform one). Moreover, this problem appears only when an application is trying to start under Windows Seven Ultimate
N x64 (ENU) (for example, the same code works fine with Windows Seven Ultimate x64 (RUS) (without N index, with Media Player)). On OSes for 80x86 the problem doesnât appear.
So, let me emphasize the key moment: when the code contains the "#pragma comment(lib, "Netapi32.lib")" line, contains calls to the CoInitializeEx/CoInitialize and CoUninitialize and its built for x86 (IA-32) platform, an application fails to start
correctly under Windows Seven Ultimate N x64 (ENU). Application with the same code works fine under Windows XP Professional x86, Windows Server 2003 x86, Windows Seven Ultimate x64 (RUS), Windows Seven Ultimate N x86 (ENU) (I didnt test the
issue with Windows Vista).
By the way, if an application code doesnt use the pragma directive, but specifies the netapi32.lib as linker input (in the project property pages), the issue goes away.
I tried to create a sample that doesnt require CRT. When the project was rebuilt for "Win32" or "x64" platform, linker failed with the error: "error LNK2019: unresolved external symbol __imp__DsGetDcNameW@24 referenced in function _wmain" when I used
"#pragma comment(lib, "Netapi32.lib")". Does linker think that DsGetDcNameW is implemented in CRT libs, because the pragma directive writes something wrong into the obj file? Well, this problem is immune against Windows OS version -- it doesnt matter
what Windows hosts VS 2010 -- for "Win32" solution/project platform build always fails.
So, my question is: whats wrong? Is it my fault, or does pragma do something wrong? Or is this something else?
Tools versions (x86) and OS, where builds were made:<br/>
CL: 16.00.30319.01.<br/>
LINK: 10.00.30319.01.<br/>
RC: 6.1.7600.16385.<br/>
Windows 6.1 (build 7600): Windows 7 Ultimate N x64 ENU.
Here are the complete samples I used for this post:
<ol>
<a title="pragmlib.zip, 3.75 kB http://files.myopera.com/std-shared-ptr/files/pragmlib.zip pragmlib.zip â simple VS 2010 solution as it was made by VS "New Project" wizard (with some oversimplifying modifications).
<a title="pragmlib-nocrt.zip, 3.74 kB http://files.myopera.com/std-shared-ptr/files/pragmlib-nocrt.zip pragmlib-nocrt.zip â the same as pragmlib.zip, but project here doesnt require CRT to work (linker has /NODEFAULTLIB /ENTRY:"wmain"
switches). </ol>
View the full article