Get LocalTime of a different Time zone c++ - c++

System is in UTC, Is there a way to get a local time of a specific timezone?
Most windows api's return values based on system time.
If there is any api where we could pass the timezone indication and get the localtime?
Also, read different api's windows provides, and thought this one : "EnumDynamicTimeZoneInformation"
could be of use to me, but i cant get this to run, i see a undefined identifier error.
error C3861: 'EnumDynamicTimeZoneInformation': identifier not found
Included windows.h as mentioned in this link:
https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-enumdynamictimezoneinformation?redirectedfrom=MSDN
On getting info from the above api, i can try passing the same to :
SystemTimeToTzSpecificLocalTime
and hoping that would do it.
Can anyone suggest what i'm missing.
Trying this on VS2010
File: time.cpp
#ifndef WINVER
#define WINVER 0x0602
#endif
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0602
#endif
#include <windows.h>
#include<time.h>
#include<iostream>
int main(){
DYNAMIC_TIME_ZONE_INFORMATION d_tz;
memset(&d_tz,0,sizeof(d_tz));
DWORD res=0;
res = EnumDynamicTimeZoneInformation(1, &d_tz);//fetch specific timezone info
/*Use this next*/
//SystemTimeToTzSpecificLocalTime();
return 0;
}

Comprehensive comments, the following example works for me:
#define WINVER 0x0602
#define _WIN32_WINNT 0x0602
#include <windows.h>
#include<time.h>
#include<iostream>
int main() {
DYNAMIC_TIME_ZONE_INFORMATION d_tz;
memset(&d_tz, 0, sizeof(d_tz));
DWORD res = 0;
res = EnumDynamicTimeZoneInformation(1, &d_tz);//fetch specific timezone info
/*Use this next*/
SYSTEMTIME st = { 0 };
SYSTEMTIME lt = { 0 };
GetSystemTime(&st);
SystemTimeToTzSpecificLocalTimeEx(&d_tz,&st, &lt);
WCHAR time[250] = { 0 };
GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, &lt, L"HH':'mm':'ss tt", time, 250);
std::wcout << L"Timezone: " << d_tz.TimeZoneKeyName << std::endl;
std::wcout << lt.wYear << L"/" << lt.wMonth << L"/" << lt.wDay << L" " << time << std::endl;
return 0;
}
Use EnumDynamicTimeZoneInformation get a DYNAMIC_TIME_ZONE_INFORMATION instance and then pass it to SystemTimeToTzSpecificLocalTimeEx with your SYSTEMTIME. Finally get the specific local time.
Result:
Timezone: Alaskan Standard Time
2021/2/2 17:25:39 PM

Related

FindResource call returns NULL for text file with type RCDATA

I'm writing a C++ program that needs to handle large chunks of data, specifically text files, however the data is longer than the given string limit. As a result I am attempting to load a text file as a resource file, however whenever I call FindResource the response is a null handle.
I have gone over other stack overflow posts, and MSDN to attempt to correctly implement this functionality however nothing I have tried has returned a valid handle.
C++ code:
HGLOBAL res_handle = NULL;
HRSRC res;
char * res_data;
DWORD res_size;
auto g_hInstance = GetModuleHandle(NULL);
res = FindResource(g_hInstance, MAKEINTRESOURCE(MY_RESOURCE), RT_RCDATA);
std::cout << res << std::endl;
std::cout << GetLastError() << std::endl;
res_handle = LoadResource(NULL, res);
std::cout << GetLastError() << std::endl;
res_data = (char*)LockResource(res_handle);
std::cout << GetLastError() << std::endl;
res_size = SizeofResource(NULL, res);
std::cout << GetLastError() << std::endl;
Output:
0000000000000000
1813
87
87
87
Resource.h:
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Resource.rc
//
#define MY_RESOURCE 300
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40002
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
Resource.rc:
MY_RESOURCE RCDATA "C:\\Users\\foobar\\Desktop\\projects\\foobar\\test0.txt"
This works for me. I suspect something about your build setup is going wrong.
I started with an empty project in Visual Studio 2017 and the only thing I changed in the project settings was Configuration Properties > General > Character Set > "Use Unicode Character Set"
Source.cpp
#include <iostream>
#include <Windows.h>
#include "resource.h"
int main() {
auto hinst = ::GetModuleHandleW(NULL);
std::cout << hinst << std::endl;
auto hrsrc = ::FindResourceW(hinst, MAKEINTRESOURCE(IDTHING), RT_RCDATA);
std::cout << hrsrc << std::endl;
auto hglob = ::LoadResource(hinst, hrsrc);
std::cout << hglob << std::endl;
return 0;
}
resource.h
#define IDTHING 300
Resource.rc
#include "resource.h"
IDTHING RCDATA "C:\\Windows\\notepad.exe"
I completely avoided all the auto-generated resource stuff from VS and just wrote them as plain text files.
If you run in the debugger, stop after hglob is assigned and drop its value into a memory window, I can clearly see the PE header of notepad.exe.
When you receive error codes from GetLastError(), you should either call FormatMessage API (with FORMAT_MESSAGE_FROM_SYSTEM flag) or use error lookup tool, “Tools / Error Lookup” in visual studio.
Code 1813 translates into the following message: “The specified resource type cannot be found in the image file.”
As you see, it complains about resource type.
I don’t think you need RCDATA. It’s something very old from 16 bit windows. In Win32, custom resources types are strings, not integers. RCDATA is not even supported in the IDE.
The correct way — right click on your .rc file, “Add Resource”, “Import”, browse for the file you want to include, visual studio will ask you resource type, write any string e.g. text will do, then pass that string as the last parameter of FindResource function. If you're building with the default project settings, it's Unicode, so you'll need to pass Unicode string L"text" there.

The LPCSTR type string is garbled or displayed error

I have a LPCSTR that I want to convert to std::string or char*.
LPCSTR strName;
_tprintf(_T("%s\n"), strName);
I'm trying to get all the audio equipment on the computer and displayed, but to get the LPCSTR type of direct output is garbled, use the above code to output the correct results.
Is there a way to save the correct output?
The following is the complete code:
Add a dependency to the property:
comctl32.lib;winmm.lib;dsound.lib;dxguid.lib;odbc32.lib;odbccp32.lib
ListSoundDev.h
#ifndef _LISTSOUNDDEV_HEAD_
#define _LISTSOUNDDEV_HEAD_
#include<tchar.h>
#include <dshow.h>
#include<iostream>
#include<vector>
#include<mmsystem.h>
#include<mmreg.h>
#include<dsound.h>
#pragma comment(lib, "strmiids.lib")
#pragma comment(lib, "Quartz.lib")
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "dsound.lib")
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "strmiids")
using namespace std;
typedef struct _DevItem
{
LPCSTR strName;
GUID guid;
} DevItem;
#endif
main.cpp
#include"ListSoundDev_head.h"
std::vector<DevItem> m_CapDevices;
BOOL CALLBACK DSEnumCallback(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext)
{
std::vector<DevItem> *pLst = (std::vector<DevItem> *) lpContext;
if (pLst)
{
DevItem item;
memset(&item, 0, sizeof(item));
item.strName = lpcstrDescription;
if (lpGuid)
item.guid = *lpGuid;
else
item.guid = GUID_NULL;
pLst->push_back(item);
return TRUE;
}
return FALSE;
}
int main()
{
std::vector<DevItem>::iterator it;
HRESULT hr = S_OK;
setlocale(LC_ALL, "chs");
hr = DirectSoundCaptureEnumerate((LPDSENUMCALLBACKW)DSEnumCallback, (LPVOID)&m_CapDevices);
for (it = m_CapDevices.begin(); it != m_CapDevices.end(); it++){
_tprintf(_T("%s\n"), it->strName);//output correct
printf("%s\n",it->strName);//output error
std::cout << it->strName << std::endl;//output error
}
}
Expected output:
麦克风 (Realtek High Definition Au
Actual output:
KQ螛
Expected output:
Realtek Digital Input (Realtek
Actual output:
R
How can I that printf() or std::cout can directly output the correct results?
Thank you very much for your answer, I have solved this problem.
The solution is to use the following code to convert.
The character set is Unicode.
char newStr[100];
wcstombs(newStr, (wchar_t*)it->strName, 100);
printf("newStr=%s\n", newStr);
The character set is Multibyte
printf("%s\n", it->strName);
However, when I write this program in the C + + console to obtain the name of the audio device for the microphone (Realtek High Definition Au, but in MFC using this code to get the device name for the microphone (Realtek High Definition Audio) What is the reason?

Make a VB-dll and load it in C++ application

I have a problem I've been struggeling with for a full week now, and I'm not able to solve it by myself. I've been googeling, and searching in all kind of forums... I have found lots of "this might work", tried it, but no, no success. If anyone have any clue, please, please, help me!
I'v got, from an external source, lots of classes and functions written in VB that I need to be able to use from a C++ application. My first though was: no problem, I turn the VB code into a dll, and load it from my C++-program. This was though harder than I ever could imagine. My C++-program is not written in Visual Studio, but for simplicity I started with trying to load my VB dll (written in Visual Studio 2010) from a Visual Studio C++ application. This is my code so far:
VB-code : DllModule : Class-library project
DllModule.vb
Namespace DllModule
Public Module DllModule
Public Const DLL_PROCESS_DETACH = 0
Public Const DLL_PROCESS_ATTACH = 1
Public Const DLL_THREAD_ATTACH = 2
Public Const DLL_THREAD_DETACH = 3
Public Function DllMain(ByVal hInst As Long, ByVal fdwReason As Long,
ByVal lpvReserved As Long) As Boolean
Select Case fdwReason
Case DLL_PROCESS_DETACH
' No per-process cleanup needed
Case DLL_PROCESS_ATTACH
DllMain = True
Case DLL_THREAD_ATTACH
' No per-thread initialization needed
Case DLL_THREAD_DETACH
' No per-thread cleanup needed
End Select
Return True
End Function
'Simple function
Public Function Add(ByVal first As Integer, ByVal sec As Integer) As Integer
Dim abc As Integer
abc = first + sec
Return abc
End Function
End Module
End Namespace
DllModule.def
NAME DllModule
LIBRARY DllModule
DESCRIPTION "My dll"
EXPORTS DllMain #1
Add #2
C++-code : TryVbDllLoad : Console application
TryVbDllLoad.cpp
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <strsafe.h>
extern "C" {
__declspec(dllimport) int __stdcall Add(int, int);
}
typedef int (__stdcall *ptf_test_func_1_type)(int, int);
int __cdecl _tmain(int argc, _TCHAR* argv[])
{
HINSTANCE hdll = NULL;
hdll = LoadLibrary("DllModule.dll"); // load the dll
if(hdll) {
ptf_test_func_1_type p_func1=(ptf_test_func_1_type)GetProcAddress(hdll,"Add");
if(p_func1) {
int ret_val = (*p_func1)(1, 2);
} else {
DWORD dw = GetLastError();
}
FreeLibrary(hdll); // free the dll
} else {
DWORD dw = GetLastError();
}
return 0;
}
I can load the dll, but GetProcAddess returns NULL with error code 127 (the specified procedure could not be found).
I have tried to load the dll from a VB-application. This works (even without the .def-file). But I'm guessing there is no proper entry point created that the C++ application can use (when I open the dll in Dependency Walker I see no entry point or functions). I've tried compiling the VB-code both with and without "Register for COM interop".
1) What am I doing wrong?
2) If there isn't any nice way to solve this properly, what can I do instead of creating a dll? Is there any other way I can use the VB-classes and functions in my C++ application?
Kind Regards
Sara
Thanks for your answer Mare!
There must be some kind of error in my dll though, cause when I try to register is using regsvr32 I get: "The module C:/tmp/DllModule.dll was loaded, but the start address for DllRegisterServer was not found. Check that C:/tmp/DllModule.dll is a valid DLL- or OCX-file and try again."
Also, when I use
#import "C\tmp\DllModule.dll"
I get
fatal error C1083: Cannot open type library file: 'c:\tmp\dllmodule.dll'
I looked at the link with the tutorial, but there is a small problem: there are no such thing as "ActiveX DLL" to choose among all the project types. And yes, I do have Visual Studio 2010 Professional (a trial version, but still).
-- Sara
Thanks for all the input. I've come across another way to solve my problem, using a multifile assembly rather than my first dll approach.
I followed this HowTo-section: http://msdn.microsoft.com/en-us/library/226t7yxe.aspx#Y749
VB-code : DllModule : Class-library project
DllModule.vb
Imports System.Runtime.InteropServices
Namespace DllModuleNS
Public Class Class1
Public Function ClassAdd(ByRef first As Integer, ByRef sec As Integer) As Integer
Dim abc As Integer
abc = first + sec
Return abc
End Function
End Class
End Namespace
This file I compiled using both visual studio (to produce DllModule.dll-file) and cmd-line:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Vbc.exe /t:module DllModule.vb
(to produce DllModule.netmodule-file).
C++-code : TryVbDllLoad : Console application
TryVbDllLoad.cpp
#using <mscorlib.dll>
#using ".\..\ClassLibrary1\DllModule.netmodule"
using namespace DllModule::DllModuleNS;
int _tmain(int argc, _TCHAR* argv[])
{
Class1^ me = gcnew Class1();
int a = 1, b = 2;
int xx = me->ClassAdd(a, b);
return 0;
}
In the TryVBDllLoad-project properties I changed:
Common Properties -> Framework and References : added DllModule-project as reference
Configuration Properties -> C/C++ -> General : /clr flag set
Configuration Properties -> Linker -> Input : Add Module To Assembly set to path to DllModule.netmodule (/ASSEMBLYMODULE:"DllModule.netmodule")
This resulted in that I could use the VB-class Class1 in VC++ code!
PROBLEM SOLVED!
I now took it one step further, and changed the TryVBDllLoad-project to a dll:
Configuration Properties -> General : Configurationtype Dynamic Library (.dll)
Configuration Properties -> Linker -> System : SubSystem Windows (/SUBSYSTEM:WINDOWS)
TryVbDllLoadClass.h
#ifndef TryVbDllLoadClass_H
#define TryVbDllLoadClass_H
class TryVbDllLoadClass
{
public:
TryVbDllLoadClass();
int Add(int a, int b);
};
#endif // TryVbDllLoadClass_H
TryVbDllLoadClass.cpp
#include "TryVbDllLoadClass.h"
#using <mscorlib.dll>
#using ".\..\ClassLibrary1\DllModule.netmodule"
using namespace DllModule::DllModuleNS;
TryVbDllLoadClass::TryVbDllLoadClass() {}
int TryVbDllLoadClass::Add(int a, int b)
{
Class1^ me = gcnew Class1();
int xx = me->ClassAdd(a, b);
return xx;
}
DllExport.h
#ifndef DLLEXPORT_H
#define DLLEXPORT_H
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#ifdef __dll__
#define IMPEXP __declspec(dllexport)
#else
#define IMPEXP __declspec(dllimport)
#endif // __dll__
extern "C" {
IMPEXP int __stdcall AddFunction(int);
}
#endif // DLLEXPORT_H
DllMain.h
#define __dll__
#include "dllExport.h"
#include " TryVbDllLoadClass.h"
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
return 1;
}
TryVbDllLoadClass * my;
IMPEXP int __stdcall AddFunction(int first, int second)
{
my = new TryVbDllLoadClass();
int res = my->Add(first, second);
delete my;
return res;
}
This dll I could then add to a non-visual-studio project just like a normal dll:
C++-code : LoadDll : Non-Visual-Studio-project (CodeBlocks in this case)
main.cpp
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "dllExport.h"
typedef int( * LPFNDLL_CREATE)(int, int);
HINSTANCE hDLL;
LPFNDLL_CREATE func;
using namespace std;
int main()
{
cout << "Hello world!" << endl;
int key = 35;
hDLL = LoadLibrary("TryVbDllLoadClass.dll");
if(hDLL)
{
cout << "Loaded: " << hDLL << endl;
func = (LPFNDLL_CREATE) (GetProcAddress(hDLL, "_AddFunction#4"));
if(func != NULL)
{
cout << "Connected: " << func << endl;
cout << "Function returns: " << func(key, key) << endl;
}
else cout << " ::: fail: " << GetLastError() << endl;
FreeLibrary(hDLL);
cout << "Freed" << endl;
}
else cout << " ::: fail: " << GetLastError() << endl;
printf("-> Goodbye world!\n");
return 0;
}
This way I can use the VB-classes given to me in my existing C++-project created outside Visuabl Studio. Finally...:)
With VB you do not get a "normal" DLL (at least this was the case in former times).
And you do not get Entry Points for functions.
But as i understood you, you have the VB source code and you can do with it whatever
is necessary. Here is a possible solution:
http://www.codeproject.com/Articles/21/Beginner-s-Tutorial-Calling-Visual-Basic-ActiveX-D
but try out first this less complicated way,
because i think a VB dll is always a COM dll, so you can:
register the dll using the Windows command
regsvr32 F:\proj\VBDllModule.dll
now your C++ code :
#import "F:\proj\VBDllModule.dll"
using namespace DllModule;
void CDialogTestDlg::OnButton1()
{
HRESULT hresult;
CLSID clsid;
_CTest *t; // a pointer to the CTest object
_bstr_t bstrA = L"hello";
_bstr_t bstrB = L" world";
_bstr_t bstrR;
::CoInitialize(NULL);
hresult=CLSIDFromProgID(OLESTR("VBTestLib.CTest"), &clsid);
hresult= CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,
__uuidof(_CTest),(LPVOID*) &t);
if(hresult == S_OK)
{
bstrR = t->vbConcat(bstrA , bstrB);
AfxMessageBox((char*)bstrR);
}
}

MsiEnumProductsEx Not Working

I have the following application, to check installed programs in a system:
#include <iostream>
#include <Msi.h>
#include <Windows.h>
using namespace std;
void main()
{
UINT ret;
DWORD dwIndex = 0;
DWORD dwContext = MSIINSTALLCONTEXT_ALL;
char szInstalledProductCode[39] = {0};
char szSid[128] = {0};
const char* szUserSid = "s-1-1-0";
DWORD cchSid;
MSIINSTALLCONTEXT dwInstalledContext;
do
{
memset(szInstalledProductCode, 0, sizeof(szInstalledProductCode));
cchSid = sizeof(szSid)/sizeof(szSid[0]);
ret = MsiEnumProductsEx(
NULL, // all the products in the context
szUserSid, // i.e.Everyone, all users in the system
dwContext,
dwIndex,
szInstalledProductCode,
&dwInstalledContext,
szSid,
&cchSid
);
if(ret == ERROR_SUCCESS)
{
char* name = MsiGetProductInfoEx (
szInstalledProductCode,
cchSid == 0 ? NULL : szSid,
dwInstalledContext,
INSTALLPROPERTY_INSTALLEDPRODUCTNAME
);
char* version = MsiGetProductInfoEx (
szInstalledProductCode,
cchSid == 0 ? NULL : szSid,
dwInstalledContext,
INSTALLPROPERTY_VERSIONSTRING
);
cout << name << endl;
cout << " - " << version << endl;
dwIndex++;
}
} while(ret == ERROR_SUCCESS);
}
I am using Microsoft Visual C++ Express 2010. The application is MBCS. In studio, these four things are in red (error):
MSIINSTALLCONTEXT_ALL
MSIINSTALLCONTEXT
MsiEnumProductsEx
MsiGetProductInfoEx
I linked the Msi.lib (Project properties -> Linker -> Input -> Additional Dependencies). I am just trying to figure out how MsiEnumProductsEx function works. I know there are other questions around, but I just can't understand why it isn't working because I think that I have everything for the functions to be available, at least. Thanks!
The MSIINSTALLCONTEXT_ALL (and related identifiers) are defined in <msi.h> only if _WIN32_MSI >= 300. You have to tell the Windows SDK what the minimum OS version you're targeting is, by defining a few macros before installing any SDK headers (like <msi.h> or <windows.h>).
You do that according to this MSDN page.
Once you've defined a suitable minimum version (looks like Windows XP SP2 and up), then _WIN32_MSI will be set to an appropriate level, and you should get the symbols.

C++ Windows - How to get process path from its PID

How can I retrieve a process's fully-qualified path from its PID using C++ on Windows?
Call OpenProcess to get a handle to the process associated with your PID. Once you have a handle to the process, call GetModuleFileNameEx to get its fully-qualified path. Don't forget to call CloseHandle when you're finished using the process handle.
Here's a sample program that performs the required calls (replace 1234 with your PID):
#include <windows.h>
#include <psapi.h> // For access to GetModuleFileNameEx
#include <tchar.h>
#include <iostream>
using namespace std;
#ifdef _UNICODE
#define tcout wcout
#define tcerr wcerr
#else
#define tcout cout
#define tcerr cerr
#endif
int _tmain(int argc, TCHAR * argv[])
{
HANDLE processHandle = NULL;
TCHAR filename[MAX_PATH];
processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, 1234);
if (processHandle != NULL) {
if (GetModuleFileNameEx(processHandle, NULL, filename, MAX_PATH) == 0) {
tcerr << "Failed to get module filename." << endl;
} else {
tcout << "Module filename is: " << filename << endl;
}
CloseHandle(processHandle);
} else {
tcerr << "Failed to open process." << endl;
}
return 0;
}
Some notes to Emerick Rogul's solution:
Don't forget to add 'psapi.lib' to linker (additional dependencies).
I also changed PROCESS_ALL_ACCESS to PROCESS_QUERY_INFORMATION | PROCESS_VM_READ because I got:
Failed to open process.
If it's compiled as a 32 bit application it will fail to get the name of 64 bit processes ("Failed to get module filename.")
I didn't have very much luck with GetModuleFileNameEx and QueryFullProcessImageName is only available on Vista or higher. I was however able to get the path for a process by using GetProcessImageFilename. It returns the windows kernel path but you can use QueryDosDevice to compare the device path returned by GetProcessImageFilename with its proper drive path.
This page shows how to normalize an windows kernel path returned by GetProcessImageFilename (see NormalizeNTPath function):
http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/c48bcfb3-5326-479b-8c95-81dc742292ab/
Have you tried QueryFullProcessImageName?
Sometimes GetModuleFileNameEx returns the 299 error code (I don't know why)
The only method that works for all versions of Windows, including XP is in Nathan Moinvaziri answer:
check the provided url:
Windows API to Get a Full Process Path