We have a legacy perl code base that includes the below line:
use Win32::OLE::Const 'Microsoft Excel';
This has worked traditionally but is not working on newer 64-bit installations, such as Windows 10.
The error appears to be in the OLE.xs source as below, but I have a limited understanding of Windows functions and XS in general.
err = RegQueryValueA(hKeyLangid, "win32", szFile, &cbFile);
If this query fails, it never calls Win32::OLE::Const::_Typelib which is the function that stores the result. Checking my registry, the keys are indeed Win64 and not win32. Other keys that worked either have just win32 or both.
Is there a way to resolve this issue without editing the legacy module? It is widely used and any changes would involve some risk so I'm looking at alternatives first.
I'm aware we can do the below, but it doesn't stop the other Win32::OLE::Const line causing an error if it's not removed.
my $Excel = Win32::OLE->new('Excel.Application', 'Quit');
my $xl = Win32::OLE::Const->Load($Excel);
I'll provide a fix in case anyone wants to use it. It's not clear to me whether Win32::OLE is still being maintained, as the issues list at https://rt.cpan.org/Public/Bug/Display.html?id=48858 raised this exact item a number of months ago, so I'm not sure where to submit a patch.
As noted in that link there are a few ways to resolve this (such as giving preference to the win64 entry if both exist), however I've decided it would be best in our case to only query the win64 folder if win32 does not return anything useful.
To do this, in OLE.xs search for win32 and change as below.
err = RegQueryValueA(hKeyLangid, "win32", szFile, &cbFile);
// check win64 if win32 failed
if (err != ERROR_SUCCESS || cbFile <= 1)
err = RegQueryValueA(hKeyLangid, "win64", szFile, &cbFile);
Related
I would like to create symbolic links to my data from my program in a cross-platform manner. For *nix systems, there is the symlink. For Windows, I found the function CreateSymbolicLink from this answer in SO and I am running it in this way:
int test = CreateSymbolicLink(input_fileName.c_str(), ouput_fileName.c_str(), 0);
But test always returns 0, which means that the function failed (and the file specified in output_fileName is indeed non-existent). What am I doing wrong?
Thanks in advance!
UPDATE:
I did run GetLastError right after the above call:
DWORD err = GetLastError();
with err = 1314. Thanks #David
UPDATE 2:
According to #David's reply, Windows does not let non-admins create soft-links. I am keeping the question open if a future iteration of Win API changes this. Then I will update the answer. As of 26/March/2015, #David's answer is correct.
From the documentation:
If the function fails, the return value is zero. To get extended error information, call GetLastError.
You don't appear to have called GetLastError. You should do so. A likely error code is ERROR_PRIVILEGE_NOT_HELD which has value 1314. You'll get this if the calling process does not have enough rights. You need to be running as an elevated administrator to use this function.
use c++17 create_symlin instead https://en.cppreference.com/w/cpp/filesystem/create_symlink
It works fine.
I grabbed the USB stick that was formatted as FAT for my test. the above code should work if you are using the correct volume format and you are in the Administrator Group. If you are in Windows 10 you should not need to Adjust Token Privileges, and you do not need UNC for the parameters.
I have an MFC application. It has a CMap which contains certain data objects, the map is declared as CMap<DWORDLONG, DWORDLONG,_ItemsObj*,_ItemsObj*> where _ItemsObj is a structure that contains various data.
The problem I'm facing is that when I try to search for an entry the Lookup method fails unexpectedly on x64 builds (and ONLY on x64 builds).
Here's the code I'm using
BOOL IsItemExist(DWORDLONG dwid)
{_ItemsObj* pObj=NULL;
if(!m_Itemsmap.Lookup(dwid,pObj))
{return FALSE;}
return TRUE;
}
Now this works perfectly on a 32-bit build of my application. However on an x64 build the Lookup always fails even though the items are present in the map and the key I'm looking for is present in the map.
I think its somewhat related to a build configuration issue, I have checked the linking properties and build configuration for both the x86 and the x64 option for the app project and they use the exact same configuration except for the target machine option (which should be different).
Can someone please help me fix this, I've been looking all over the internet for a solution but could not find anything.
Oh and I'm using VS 2010 SP1
Regards
There are five global helper functions that CMap, CList and CArray uses. They are CompareElements, CopyElements, DumpElements, HashKey and SerializeElements. Your problem is likely with SerializeElements which CMap uses to to store collection element.
The other thing to try is to declare your CMap as
CMap < DWORDLONG, DWORDLONG, _ItemsObj,_ItemsObj*>
> I have visual studio c++ express and a NVIDIA GeForce 7900 GS. I'm using glew to get at the openGL extensions. Calling glGenBuffers crashes as its a NULL pointer tho. I have an open GL context before I make the call ( wglGetCurrentContext() != NULL ). I'm calling glewInit() before the call. glewGetString( GLEW_VERSION ) is returning GLEW_VERSION_1_5. What am I doing wrong ? Is the card too old ? Is it the driver ?
Remember to make a glewInit() call in your code so that you get valid pointers to GL functions.
Hope it helps.
Without seeing your code it would be difficult to tell, but what you are attempting to do seems like it could be helped a lot by using GLee. It is designed to load all current extensions and you have the ability to check what is supported, e.g. :
#include <gl\GLee.h> // (no need to link to gl.h)
...
if (GLEE_ARB_multitexture) //is multitexture support available?
{
glMultiTexCoord2fARB(...); //safe to use multitexture
}
else
{
//fallback
}
The above was shamelessly copy/pasted from the GLee site, but it displays the functionality I'm trying to showcase.
You need to call glewInit() post having a valid context. And that would be, in the world of glew, after you've called glfwMakeContextCurrent(myWindow);
I have actually run into this problem with GLEW. For me, it was nullifying the function pointer for glGenerateMipmap. I fixed it by simply restoring the pointer to the appropriate function. This is my example in Linux:
glGenerateMipmap = (void(*)(GLenum))
glXGetProcAddressARB((GLubyte*)"glGenerateMipmap");
There is a WGL equivalent for glXGetProcAddress; I just don't remember the name off the top of my head. Try manually restoring the functions using this method. If you come across many functions that are null, something is definitely wrong in your setup process. The only other functions I recall having to restore were glGenVertexArrays, glBindVertexArray, and glDeleteVertexArrays. If your glGenBuffers is null, odds are that glBindBuffer and glDeleteBuffers are null as well. :(
Test if the desired extension is actually supported by checking the string returned by glGetString(GL_EXTENSIONS); if it's not there you know what's causing your problems.
We have a native C++ application running via COM+ on a windows 2003 server. I've recently noticed from the event viewer that its throwing exceptions, specifically the C0000005 exception, which, according to http://blogs.msdn.com/calvin_hsia/archive/2004/06/30/170344.aspx means that the process is trying to write to memory not within its address space, aka access violation.
The entry in event viewer provides a call stack:
LibFmwk!UTIL_GetDateFromLogByDayDirectory(char const *,class utilCDate &) + 0xa26c
LibFmwk!UTIL_GetDateFromLogByDayDirectory(char const *,class utilCDate &) + 0x8af4
LibFmwk!UTIL_GetDateFromLogByDayDirectory(char const *,class utilCDate &) + 0x13a1
LibFmwk!utilCLogController::GetFLFInfoLevel(void)const + 0x1070
LibFmwk!utilCLogController::GetFLFInfoLevel(void)const + 0x186
Now, I understand that its giving me method names to go look at but I get a feeling that the address at the end of each line (e.g. + 0xa26c) is trying to point me to a specific line or instruction within that method.
So my questions are:
Does anyone know how I might use this address or any other information in a call stack to determine which line within the code its falling over on?
Are there any resources out there that I could read to better understand call stacks,
Are there any freeware/opensource tools that could help in analysing a call stack, perhaps by attaching to a debug symbol file and/or binaries?
Edit:
As requested, here is the method that appears to be causing the problem:
BOOL UTIL_GetDateFromLogByDayDirectory(LPCSTR pszDir, utilCDate& oDate)
{
BOOL bRet = FALSE;
if ((pszDir[0] == '%') &&
::isdigit(pszDir[1]) && ::isdigit(pszDir[2]) &&
::isdigit(pszDir[3]) && ::isdigit(pszDir[4]) &&
::isdigit(pszDir[5]) && ::isdigit(pszDir[6]) &&
::isdigit(pszDir[7]) && ::isdigit(pszDir[8]) &&
!pszDir[9])
{
char acCopy[9];
::memcpy(acCopy, pszDir + 1, 8);
acCopy[8] = '\0';
int iDay = ::atoi(&acCopy[6]);
acCopy[6] = '\0';
int iMonth = ::atoi(&acCopy[4]);
acCopy[4] = '\0';
int iYear = ::atoi(&acCopy[0]);
oDate.Set(iDay, iMonth, iYear);
bRet = TRUE;
}
return (bRet);
}
This is code written over 10 years ago by a member of our company who has long since gone, so I don't presume to know exactly what this is doing but I do know its involved in the process of renaming a log directory from 'Today' to the specific date, e.g. %20090329. The array indexing, memcpy and address of operators do make it look rather suspicious.
Another problem we seem to have is that this only happens on the production system, we've never been able to reproduce it on our test systems or development systems here, which would allow us to attach a debugger.
Much appreciated!
Andy
Others have said this in-between the lines, but not explicitly. look at:
LibFmwk!UTIL_GetDateFromLogByDayDirectory(char const *,class utilCDate &) + 0xa26c
The 0xa26c offset is huge, way past the end of the function. the debugger obviously doesn't have the proper symbols for LibFmwk so instead it's relying on the DLL exports and showing the offset relative to the closest one it can find.
So, yeah, get proper symbols and then it should be a breeze. UTIL_GetDateFromLogByDayDirectory is not at fault here.
if you really need to map those addresses to your functions - you'll need to work with .MAP file and see where those addresses really point to.
But being in your situation I would rather investigate this problem under debugger (e.g. MSVS debugger or windbg); as alternative (if crash happens at customer's site) you can generate crash dump and study it locally - it can be done via Windows MiniDumpWriteDump API or SysInternals ProcDump utility (http://download.sysinternals.com/Files/procdump.zip).
Make sure that all required symbol files are generated and available (also setup microsoft symbol server path so that windows DLLs' entry points get resolved also).
IMHO this is just the web site you need: http://www.dumpanalysis.org - which is the best resource to cover all your questions.
Consider also taking a look at this PDF - http://windbg.info/download/doc/pdf/WinDbg_A_to_Z_color.pdf
Point 2 and 3 are easily answered:
3rd Point. Any debugger. That's what they are made for. Set your debugger to break on this special exception. You should be able to click yourself through the callstack and find the different calls on the stack (at least delphi can do this, so visual studio should be able as well). Compile without optimisations if possible. OllyDBG might work as well - perhaps in combination with its trace functionality.
2nd Point. Any information about x86 Assembler, Reverseengineering ... Try: OpenRCE, NASM Documentation, ASM Community.
1st Point. The callstack tells you the functions. I don't know if it is written in order or in opposite order - so it might be that the first line is the last called function or the first called function. Follow the calls with the help of the debugger. Sometimes you can change between asm and code (depending on the debugger, map files ...). If you don't have the source - learn assembler, read about reverse engineering. Read the documentation of the functions you call in third party components. Perhaps you do not satisfy a precondition.
If you can tell a bit more about the programm (which parts of the source code do you have, is a library call involved?, ...)
Now some code-reading:
The function accepts a pointer to a zero terminated string and a reference to a date object. The pointer is assumed to be valid!
The function checks wether the string is in a specific format (% followed by 8 digits followed by a \0). If this is not the case, it returns false. This check (the big if) accesses the pointer without any validity checks. The length is not checked and if the pointer is pointing somewhere in the wild, this space is accessed. I don't know if a shorter string will cause problems. It shouldn't because of the way && is evaluated.
Then some memory is allocated on the stack. The number-part of the string is copied into it (which is ok) and the buffer gets its \0 termination. The atois extract the numbers. This will work because of the different start-locations used and the \0-termination after each part. Somehow tricky but nice. Some comments would have made everything clear.
These numbers are then inserted into the object. It should be valid since it is passed into the function by reference. I don't know if you can pass a reference to a deleted object but if this is the case, this might be your problem as well.
Anyway - except the missing check for the string-pointer, this function is sound and not the cause of your problem. It's only the place that throws the exception. Search for arguments that are passed into this function. Are they always valid? Do some logging.
I hope I didn't do any major mistakes as I am a Delphi programmer. If I did - feel free to comment.
This question HAS had to be asked before, so it kills me to ask it again, but I can't find it for all of my google and searching stackoverflow.
I'm porting a bunch of linux code to windows, and a good chunk of it makes the assumption that everything is automatically initialized to zero or null.
int whatever;
char* something;
...and then immediately doing something that may leave 'something' null, and testing against 'something'
if(something == NULL)
{
.......
}
I would REALLY like not to have to go back throughout this code and say:
int whatever = 0;
char* something = NULL;
Even though that is the proper way to deal with it. It's just very time consuming.
Otherwise, I declare a variable, and it's initialized to something crazy if I don't set it myself.
This option doesn't exist in MSVC, and honestly, whoever coded your application made a big mistake. That code is not portable, as C/C++ say that uninitialized variables have an undefined value. I suggest setting the "treat warnings as errors" option and recompiling; MSVC should give you a warning every time a variable is used without being initialized.
No - there's no option to do that in MSVC.
Debug builds will initialize them with something else (0xcc I think), but not zero. Unfortunately, your code is bugged and needs fixed (of course this applies only to automatic variables -for statics and globals it's fine to assume they're zero initialized). I'm surprised there was any compiler that supported that behavior - if there's an option to do that in GCC, I haven't heard of it (but I'm no expert in the dusty corners of GCC).
You may hear that an earlier version of MSVC would init variables to zero in debug builds (similar to the way 0xcc is used in VS 2005), but as far as I know that's untrue.
edit ----------
Well, I'll be damned - GCC does (or did?) have the -finit-local-zero option. Looks like it's there mostly for Fortran support, I think.
I'd suggest using compiler warnings about using uninitialized variables to help you catch 99% of your problems. I know it's not a great bit of work, but it should be done if at all possible.
Interestingly, MSVC now does have the ability to do this. The Microsoft Security team wrote a blog post about it here, and there's a CppCon talk here.
Unfortunately, it doesn't seem like this option is exposed to the public. This page lists a bunch of 'hidden MSVC flags', and it includes an option called -initall, so that might be it.
What I ended-up doing was switching to /w4. At this level, it caught most of the "yeah, that's going to be an issue" areas of initialization. Otherwise, there's nothing that can change everything from being 0xcccccccc on initialization to 0x00000000 that I saw.
Massive thanks to everyone for answering this, and yes, we will tighten it up in the future.