Why does IDiaEnumSymbolsByAddr::Next crash? - pdb-files

I wanted to enumerate symbols by address but it seems IDiaEnumSymbolsByAddr::Next crash when I call it.
The documentation doesn't say anything extra about it. Minimal code to reproduce:
int main()
{
IDiaDataSource *ds;
IDiaSession *session;
IDiaEnumSymbolsByAddr *symbolEnum;
IDiaSymbol *symbol;
HRESULT hr;
ULONG fetched;
CoInitialize(NULL);
hr = makeDiaDataSource(&ds);
assert(SUCCEEDED(hr));
hr = ds->loadDataForExe(L"readpdb.exe", NULL, NULL);
assert(SUCCEEDED(hr));
hr = ds->openSession(&session);
assert(SUCCEEDED(hr));
hr = session->getSymbolsByAddr(&symbolEnum);
assert(SUCCEEDED(hr));
hr = symbolEnum->Next(1, &symbol, &fetched); // crash at this line.
assert(SUCCEEDED(hr));
printf("All is OK.\n");
return 0;
}
Is this a bug in the DIA SDK? Or maybe I'm not supposed to use the interface this way?

Related

How to decrypt data that is encrypted by OpenSSL with RSA_PKCS1_OAEP_PADDING using NCryptDecrypt?

I have difficulty to decrypt data being encrypted using OpenSSL and RSA_PKCS1_OAEP_PADDING padding option.
What I am doing is:
BCRYPT_ALG_HANDLE hCryptAlg = NULL;
BCRYPT_OAEP_PADDING_INFO paddingInfo = { 0 };
DWORD cbDecryptedMessage;
BYTE* pbDecryptedMessage = NULL;
paddingInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM;
// Open an algorithm handle.
BCryptOpenAlgorithmProvider(&hCryptAlg, BCRYPT_RSA_ALGORITHM, NULL, 0);
// Calculate the required buffer
NCryptDecrypt(m_hKeyContextFull, (LPBYTE)pEncrypted, encryptedLenInBytes, &paddingInfo, NULL, cbDecryptedMessage, &outputDataLen, NCRYPT_PAD_OAEP_FLAG | NCRYPT_SILENT_FLAG);
// After required buffer is allocated...
NCryptDecrypt(m_hKeyContextFull, (LPBYTE)pEncrypted, encryptedLenInBytes, &paddingInfo, pbDecryptedMessage, cbDecryptedMessage, &outputDataLen, NCRYPT_PAD_OAEP_FLAG | NCRYPT_SILENT_FLAG);
It fails with NTE_INVALID_PARAMETER (0x80090027). I tried different flags but none of them works.
Note: m_hKeyContextFull has already been retrieved using CryptAcquireCertificatePrivateKey function call:
m_hSystemStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE, m_storeName.c_str());
m_pCertWithKeys = CertFindCertificateInStore(m_hSystemStore, SupportedEncodings, 0, CERT_FIND_SUBJECT_STR, m_certName.c_str(), NULL);
// Obtain the private key from the certificate.
DWORD m_KeyContextSpec = 0;
HCRYPTPROV_OR_NCRYPT_KEY_HANDLE m_hKeyContextFull;
CryptAcquireCertificatePrivateKey(m_pCertWithKeys, CRYPT_ACQUIRE_SILENT_FLAG | CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG, NULL, &m_hKeyContextFull, &m_KeyContextSpec, &m_KeyContextMustBeReleased);
Note: All error checkings have been removed from code for readability.
Is there any idea what am I doing wrong?
Thanks.
I'd start by making paddingInfo valid:
BCRYPT_OAEP_PADDING_INFO paddingInfo;
paddingInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM;
paddingInfo.pbLabel = NULL;
paddingInfo.cbLabel = 0;
The current standard has the empty string label (see RFC 3447).
Moreover, as to pbDecryptedMessage:
If this parameter is NULL, this function will calculate the size needed for the decrypted data and return the size in the location pointed to by the pcbResult parameter.
So it won't decrypt anyway. You need to allocate the buffer first to the right size; a lot of Windows API's work that way: first call it with output buffer NULL and you get back the needed size somehow, in this case in outputDataLen (which you should declare!). Then allocate the outbufbuffer to that size, and call the function again with the fresh buffer, and the correct length in cbDecryptedMessage. After use, free the buffer again of course. But your comment claims to have done so?
Another suspicious fact: You use NCryptDecrypt so the first argument, should
be a hKey of the right type, while m_hKeyContextFull does not seem to have that type. CryptAcquireCertificatePrivateKey will get you an old style key handle.
You cannot mix these different Windows CryptoAPI's.
Maybe look at the NcryptImportKey function, to transfer it.
I'm not familiar with the NCrypt series of interfaces, but we implemented something similar recently in a library using the BCrypt series of interfaces. Here is the function in question, which can be seen in greater context here.
In our case prvblbtyp is LEGACY_RSAPRIVATE_BLOB and prvblbbuf and prvblbblen are described here.
static
int
asymmetric_decrypt(
const wchar_t * const prvblbtyp,
const void * const prvblbbuf, const size_t prvblblen,
const void * const ctbuf, const size_t ctlen,
void ** const ptbuf, size_t * const ptlen)
{
BCRYPT_ALG_HANDLE halg;
int res;
res = INT_MIN;
if (BCryptOpenAlgorithmProvider(
&halg, BCRYPT_RSA_ALGORITHM, NULL, 0) == STATUS_SUCCESS) {
BCRYPT_KEY_HANDLE hkey;
if (BCryptImportKeyPair(
halg,
NULL, prvblbtyp, &hkey,
(void *)prvblbbuf, prvblblen,
0) == STATUS_SUCCESS) {
BCRYPT_OAEP_PADDING_INFO inf;
ULONG len;
inf.pszAlgId = BCRYPT_SHA1_ALGORITHM;
inf.pbLabel = NULL;
inf.cbLabel = 0;
/*
* decrypt first with a NULL output buffer.
* this returns the size necessary for the buffer.
*/
if (BCryptDecrypt(
hkey,
(void *)ctbuf, ctlen,
&inf,
NULL, 0,
NULL, 0, &len,
BCRYPT_PAD_OAEP) == STATUS_SUCCESS) {
void * buf;
/*
* allocate the required buffer
* and decrypt again
*/
res = -ENOMEM;
buf = malloc(len);
if (buf) {
res = INT_MIN;
if (BCryptDecrypt(
hkey,
(void *)ctbuf, ctlen,
&inf,
NULL, 0,
buf, len, &len,
BCRYPT_PAD_OAEP) == STATUS_SUCCESS) {
*ptbuf = buf;
*ptlen = len;
res = 0;
} else {
free(buf);
}
}
}
BCryptDestroyKey(hkey);
}
BCryptCloseAlgorithmProvider(halg, 0);
}
return res;
}

Changing resolution using media foundation under win 7

I am writing an app on top media foundation under win 7, I use IMFMediaSource to query the cameras interfaces to get frames and other properties. its weird but I cant find a way to change resolution. it seems that if I used IMFCaptureSource i could use SetCurrentDeviceMediaType to change resolution but its only supported in Windows 8. so we cant change resolution under win 7 using media foundation?? is there a way to use direct show with IMFMediaSource to change resolution??
if so, can anyone help with some code sample?
thanks!
ok, so I found out eventually. Iam using IMFSourceReader to get samples from the MFMediaSource, so after configurating the SourceReader you can iterate the native media types that the camera supports like this :
HRESULT nativeTypeErrorCode = S_OK;
DWORD count = 0;
UINT32 streamIndex = 0;
UINT32 requiredWidth = 1600;
UINT32 requiredheight = 900;
while (nativeTypeErrorCode == S_OK)
{
IMFMediaType * nativeType = NULL;
nativeTypeErrorCode = m_pReader->GetNativeMediaType(streamIndex, count, &nativeType);
if(nativeTypeErrorCode != S_OK) continue;
// get the media type
GUID nativeGuid = {0};
hr = nativeType->GetGUID(MF_MT_SUBTYPE, &nativeGuid);
if (FAILED(hr)) return hr;
UINT32 width, height;
hr = ::MFGetAttributeSize(nativeType, MF_MT_FRAME_SIZE, &width, &height);
if (FAILED(hr)) return hr;
if(nativeGuid == <my type guid> && width == requiredWidth && height == requiredheight)
{
// found native config, set it
hr = m_pReader->SetCurrentMediaType(streamIndex, NULL, nativeType);
if (FAILED(hr)) return hr;
break;
}
SafeRelease(&nativeType);
count++;
}
this means that Iam not creating a new media type with the resolution I require, I get the native media type with the configuration I need, and I set it on the SourceReader.
hope it will help the future media foundation traveler... :)
You can query directshow interface from IMediaSource which can change resolution.
for ex:for Camera control properties I do like this.
IAMCameraControl* m_pCameraControl = NULL;
HRESULT hr = S_OK;
hr = pMediaSource->QueryInterface(IID_PPV_ARGS(&m_pCameraControl));
if (m_pCameraControl == NULL)
{
return E_FAIL;
}
In the same way in your case I am not sure about the interface but I guess it will be in following way.
IAMStreamConfig * m_pStreamConfig = NULL;
HRESULT hr = S_OK;
hr = pMediaSource->QueryInterface(IID_PPV_ARGS(&m_pStreamConfig ));
if (m_pCameraControl == NULL)
{
return E_FAIL;
}

c++ builder: convert video to png-snapshots with directshow

Thanks to your help I was able to search for the right words to use directshow a bit better.
I found a tutorial how to use the SampleGrabber-object here:
http://msdn.microsoft.com/en-us/library/windows/desktop/dd407288%28v=vs.85%29.aspx
I could implement it and modified it a bit so it isn't just saving the first frame, but every Frame to a PNG. For that I use corona.
However, I just guessed something around and don't quite know which buffers are containing my data and in which form.
So, I have basically 3 questions:
Am I using SavePNG right? the resulting Images are upside-down!
Can I replace the BaseFilter for the video with one that is connected to a camera?
Contains pBuffer my Imagedata so I can get rgb-byte-informations by simply type pBuffer[123]?
I'm using embarcadero's C++-Builder (XE2 16).
Here is the code I found at the website, a bit modified (error-handling removed for better view. after each hr=... there is a Failed-check):
void __fastcall TForm1::btn_kameraClick(TObject *Sender)
{
HRESULT hr = S_OK;
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEventEx *pEvent = NULL;
IBaseFilter *pGrabberF = NULL;
ISampleGrabber *pGrabber = NULL;
IBaseFilter *pSourceF = NULL;
IEnumPins *pEnum = NULL;
IPin *pPin = NULL;
IBaseFilter *pNullF = NULL;
BYTE *pBuffer = NULL;
hr = CoCreateInstance(CLSID_FilterGraph, NULL,CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&pGraph));
hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl));
hr = pGraph->QueryInterface(IID_PPV_ARGS(&pEvent));
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&pGrabberF));
hr = pGraph->AddFilter(pGrabberF, L"Sample Grabber");
hr = pGrabberF->QueryInterface(IID_PPV_ARGS(&pGrabber));
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(mt));
mt.majortype = MEDIATYPE_Video;
mt.subtype = MEDIASUBTYPE_RGB24;
hr = pGrabber->SetMediaType(&mt);
hr = pGraph->AddSourceFilter(L"C:/Users/Julian/Desktop/homogenität/1,1x_2,7y.mpg", L"Source", &pSourceF);
hr = pSourceF->EnumPins(&pEnum);
while (S_OK == pEnum->Next(1, &pPin, NULL))
{
hr = ConnectFilters(pGraph, pPin, pGrabberF);
SafeRelease(&pPin);
if (SUCCEEDED(hr))break;
}
hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&pNullF));
hr = pGraph->AddFilter(pNullF, L"Null Filter");
hr = ConnectFilters(pGraph, pGrabberF, pNullF);
hr = pGrabber->SetOneShot(TRUE);
hr = pGrabber->SetBufferSamples(TRUE);
long evCode=0;
long cbBuffer=0;
hr = pControl->Run();
hr = pEvent->WaitForCompletion(INFINITE, &evCode);
hr = pGrabber->GetCurrentBuffer(&cbBuffer, NULL);
pBuffer = (BYTE*)CoTaskMemAlloc(cbBuffer);
hr = pGrabber->GetConnectedMediaType(&mt);
CComQIPtr< IMediaSeeking, &IID_IMediaSeeking > pSeeking( pGraph );
// for(int i=0;i<10;i++){
bool hui=true;int i=0;
while(hui){
REFERENCE_TIME Start = i * UNITS;
hr = pSeeking->SetPositions( &Start, AM_SEEKING_AbsolutePositioning,NULL, AM_SEEKING_NoPositioning );
// Sleep(10);
hr = pEvent->WaitForCompletion(INFINITE,&evCode);
if(hr!=0)hui=false;
hr = pGrabber->GetCurrentBuffer(&cbBuffer, (long*)pBuffer);
if ((mt.formattype == FORMAT_VideoInfo) &&(mt.cbFormat >= sizeof(VIDEOINFOHEADER)) &&(mt.pbFormat != NULL))
{
VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)mt.pbFormat;
// hr = WriteBitmap(("hui"+(String)i+".bmp").c_str(), &pVih->bmiHeader, mt.cbFormat - SIZE_PREHEADER, pBuffer, cbBuffer);
hr = SavePNG(i,pBuffer, pVih->bmiHeader.biWidth, pVih->bmiHeader.biHeight);
}
else hr = VFW_E_INVALIDMEDIATYPE;
i++;
}
FreeMediaType(mt);
done:
CoTaskMemFree(pBuffer);
SafeRelease(&pPin);
SafeRelease(&pEnum);
SafeRelease(&pNullF);
SafeRelease(&pSourceF);
SafeRelease(&pGrabber);
SafeRelease(&pGrabberF);
SafeRelease(&pControl);
SafeRelease(&pEvent);
SafeRelease(&pGraph);
}
bool SavePNG(int i, Byte* m_pImageData,long m_Width,long m_Height)
{
// Make sure there is image data
if (!m_pImageData)
return false;
stringstream FilePath;
FilePath << "hui"<< i<<".png";
// Create a corona image
corona::Image* pImage = corona::CreateImage(m_Width, m_Height, corona::PF_R8G8B8, m_pImageData);
// Make sure the image was created
if (!pImage)
return false;
// Save the image to a PNG file
corona::SaveImage(FilePath.str().c_str(), corona::FF_PNG, pImage);
// Delete the corona image
delete pImage;
// Nothing went wrong
return true;
}
I hope I have done nothing horribly wrong... I really tried to research everything^^
Does somebody knows about my 3 questions above?
I you found something really wrong here, I would also appreciate for you to tell me, so I can fix and improve.
Regards,
Julian
Now when you have a video frame in 24-bit RGB format, all you need is to compress to PNG. You have choices here:
libpng
GDI+
WIC
Possibly, C++ bulder has native classes to cover PNG as well.
P.S. DirectShow API you are using is not DirectX, it is a part of Windows core SDK.

How to get data from directshow filter output pin?

I have direct show filter which takes an input and process it and give the result to outputpin.
I want to write this filter output data to a file...And i want to do it in its filter class.So i want to get the output pin buffer data.
Shortly how to reach final data of outputpin in its filter? How can i do it?
Not: The output pin is derived from CBaseOutputPin.This is an open source filter it "magically" :-) put wright data to its output pin which i can not figure out how yet...
Update:
Here is the siutuation:
Media Source ----> GFilter ----> FileWriter
I have source code of GFilter... I have no source code of FileWriter...What i want to make is make GFilter write its own data...I debug GFilter get some insight how its transform data but my attemp to write this data result with wrong data... So i deceide for now how to simply get data at its output pin...
Update[2]
In Filter outputpin somwhere the filter writer pass the file writer pin to IStreamPtr variable...Everthing seems to written to a variable m_pIStream which is type of [IStreamPtr]
GFilterOutput::CompleteConnect(IPin *pReceivePin)
{
// make sure that this is the file writer, supporting
// IStream, or we will not be able to write out the metadata
// at stop time
// m_pIStream is IStreamPtr type
m_pIStream = pReceivePin;
if (m_pIStream == NULL)
{
return E_NOINTERFACE;
}
return CBaseOutputPin::CompleteConnect(pReceivePin);
}
...
GFilterOutput::Replace(LONGLONG pos, const BYTE* pBuffer, long cBytes)
{
//OutputDebugStringA("DEBUG: Now at MuxOutput Replace");
// all media content is written when the graph is running,
// using IMemInputPin. On stop (during our stop, but after the
// file writer has stopped), we switch to IStream for the metadata.
// The in-memory index is updated after a successful call to this function, so
// any data not written on completion of Stop will not be in the index.
CAutoLock lock(&m_csWrite);
HRESULT hr = S_OK;
if (m_bUseIStream)
{
IStreamPtr pStream = GetConnected();
if (m_pIStream == NULL)
{
hr = E_NOINTERFACE;
} else {
LARGE_INTEGER liTo;
liTo.QuadPart = pos;
ULARGE_INTEGER uliUnused;
hr = m_pIStream->Seek(liTo, STREAM_SEEK_SET, &uliUnused);
if (SUCCEEDED(hr))
{
ULONG cActual;
hr = m_pIStream->Write(pBuffer, cBytes, &cActual);
if (SUCCEEDED(hr) && ((long)cActual != cBytes))
{
hr = E_FAIL;
}
}
}
} else {
// where the buffer boundaries lie is not important in this
// case, so break writes up into the buffers.
while (cBytes && (hr == S_OK))
{
IMediaSamplePtr pSample;
hr = GetDeliveryBuffer(&pSample, NULL, NULL, 0);
if (SUCCEEDED(hr))
{
long cThis = min(pSample->GetSize(), cBytes);
BYTE* pDest;
pSample->GetPointer(&pDest);
CopyMemory(pDest, pBuffer, cThis);
pSample->SetActualDataLength(cThis);
// time stamps indicate file position in bytes
LONGLONG tStart = pos;
LONGLONG tEnd = pos + cThis;
pSample->SetTime(&tStart, &tEnd);
hr = Deliver(pSample);
if (SUCCEEDED(hr))
{
pBuffer += cThis;
cBytes -= cThis;
pos += cThis;
}
}
}
}
return hr;
}
You have full source code, step it through with debugger until you reach the point where your filter calls IPin::Receive of the peer downstream filter, update/override code there and you have full control as for writing data into file etc.

Can you send a signal to Windows Explorer to make it refresh the systray icons?

This problem has been afflicting me for quite a while and it's been really annoying.
Every time I login after a reboot/power cycle the explorer takes some time to show up.
I've taken the step of waiting for all the services to boot up and then I login, but it doesn't make any difference.
The result is always the same: Some of the icons do not show up even if the applications have started.
I've dug a bit on the code that makes one application "stick" an icon in there, but is there an API call that one can perform so explorer re-reads all that icon info? Like invalidate or redraw or something of the sort?
Apparently, it looks like Jon was right and it's not possible to do it.
I've followed Bob Dizzle and Mark Ransom code and build this (Delphi Code):
procedure Refresh;
var
hSysTray: THandle;
begin
hSysTray := GetSystrayHandle;
SendMessage(hSysTray, WM_PAINT, 0, 0);
end;
function GetSystrayHandle: THandle;
var
hTray, hNotify, hSysPager: THandle;
begin
hTray := FindWindow('Shell_TrayWnd', '');
if hTray = 0 then
begin
Result := hTray;
exit;
end;
hNotify := FindWindowEx(hTray, 0, 'TrayNotifyWnd', '');
if hNotify = 0 then
begin
Result := hNotify;
exit;
end;
hSyspager := FindWindowEx(hNotify, 0, 'SysPager', '');
if hSyspager = 0 then
begin
Result := hSyspager;
exit;
end;
Result := FindWindowEx(hSysPager, 0, 'ToolbarWindow32', 'Notification Area');
end;
But to no avail.
I've even tried with InvalidateRect() and still no show.
Any other suggestions?
Take a look at this blog entry: REFRESHING THE TASKBAR NOTIFICATION AREA. I am using this code to refresh the system tray to get rid of orphaned icons and it works perfectly.
The blog entry is very informative and gives a great explanation of the steps the author performed to discover his solution.
#define FW(x,y) FindWindowEx(x, NULL, y, L"")
void RefreshTaskbarNotificationArea()
{
HWND hNotificationArea;
RECT r;
GetClientRect(
hNotificationArea = FindWindowEx(
FW(FW(FW(NULL, L"Shell_TrayWnd"), L"TrayNotifyWnd"), L"SysPager"),
NULL,
L"ToolbarWindow32",
// L"Notification Area"), // Windows XP
L"User Promoted Notification Area"), // Windows 7 and up
&r);
for (LONG x = 0; x < r.right; x += 5)
for (LONG y = 0; y < r.bottom; y += 5)
SendMessage(
hNotificationArea,
WM_MOUSEMOVE,
0,
(y << 16) + x);
}
Two important details for anyone using Louis's answer (from REFRESHING THE TASKBAR NOTIFICATION AREA) on Windows 7 or Windows 8:
First, as the answer was reflected to show, the window titled "Notification Area" in XP is now titled "User Promoted Notification Area" in Windows 7 (actually probably Vista) and up.
Second, this code does not clear icons that are currently hidden. These are contained in a separate window. Use the original code to refresh visible icons, and the following to refresh hidden icons.
//Hidden icons
GetClientRect(
hNotificationArea = FindWindowEx(
FW(NULL, L"NotifyIconOverflowWindow"),
NULL,
L"ToolbarWindow32",
L"Overflow Notification Area"),
&r);
for (LONG x = 0; x < r.right; x += 5)
for (LONG y = 0; y < r.bottom; y += 5)
SendMessage(
hNotificationArea,
WM_MOUSEMOVE,
0,
(y << 16) + x);
For anyone who just needs a utility to run to accomplish this, rather than code, I built a simple exe with this update: Refresh Notification Area
Include following code with yours to refresh System Tray.
public const int WM_PAINT = 0xF;
[DllImport("USER32.DLL")]
public static extern int SendMessage(IntPtr hwnd, int msg, int character,
IntPtr lpsText);
Send WM_PAINT Message to paint System Tray which will refresh it.
SendMessage(traynotifywnd, WM_PAINT, 0, IntPtr.Zero);
As far as I know that isn't possible Gustavo - it's up to each application to put its notifyicon in the systray, and ensure it's kept in the right state.
You'll notice sometimes when explorer.exe crashes that certain icons don't reappear - this isn't because their process has crashed, simply that their application hasn't put the notifyicon in the systray when the new instance of explorer.exe started up. Once again, it's the application that's responsible.
Sorry not to have better news for you!
I covered this issue last year on my Codeaholic weblog in an article entitled [Delphi] Updating SysTray.
My solution is a Delphi ActiveX/COM DLL. The download link still works (though for how much longer I don't know as my PLUG membership has lapsed.)
I use the following C++ code to get the window handle to the tray window. Note: this has only been tested on Windows XP.
HWND FindSystemTrayIcons(void)
{
// the system tray icons are contained in a specific window hierarchy;
// use the Spy++ utility to see the chain
HWND hwndTray = ::FindWindow("Shell_TrayWnd", "");
if (hwndTray == NULL)
return NULL;
HWND hwndNotifyWnd = ::FindWindowEx(hwndTray, NULL, "TrayNotifyWnd", "");
if (hwndNotifyWnd == NULL)
return NULL;
HWND hwndSysPager = ::FindWindowEx(hwndNotifyWnd, NULL, "SysPager", "");
if (hwndSysPager == NULL)
return NULL;
return ::FindWindowEx(hwndSysPager, NULL, "ToolbarWindow32", "Notification Area");
}
After lots of times trying I found that there are three issues you must to know:
The parent of hidden tray window is NotifyIconOverflowWindow, other than Shell_TrayWnd.
You shouldn't use caption parameter of FindWindowEx to find a window, because these is lots of langue versions of Windows OS, they are not always be the same title Obviously.
Use spy++ of Visual Studio to find or make assurance what you want.
So, I changed code from #Stephen Klancher and #Louis Davis, thank you guys.
The following code worked for me.
#define FW(x,y) FindWindowEx(x, NULL, y, L"")
void RefreshTaskbarNotificationArea()
{
HWND hNotificationArea;
RECT r;
GetClientRect(hNotificationArea = FindWindowEx(FW(NULL, L"NotifyIconOverflowWindow"), NULL, L"ToolbarWindow32", NULL), &r);
for (LONG x = 0; x < r.right; x += 5)
{
for (LONG y = 0; y < r.bottom; y += 5)
{
SendMessage(hNotificationArea, WM_MOUSEMOVE, 0, (y << 16) + x);
}
}
}
#Skip R, and anyone else wanting to do this in C, with this code verified compiled in a recent (most recent) mingw on Windows 10 64 bit (but with the mingw 32 bit package installed), this seems to work in Windows XP / 2003 to get rid of stale notification area icons.
I installed mingw via Chocolatey, like this:
choco install mingw --x86 --force --params "/exception:sjlj"
(your mileage may vary on that, on my system, the compiler was then installed here:
C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw32\bin\gcc.exe
and then a simple
gcc refresh_notification_area.c
yielded an a.exe which solved a stale notification area icon problem I was having on Windows 2003 (32 bit).
The code, adapted from #Stephen Klancher above is (note this may only work on Windows XP/2003, which fulfilled my purposes):
#include <windows.h>
#define FW(x,y) FindWindowEx(x, NULL, y, "")
int main ()
{
HWND hNotificationArea;
RECT r;
//WinXP
// technique found at:
// https://stackoverflow.com/questions/74723/can-you-send-a-signal-to-windows-explorer-to-make-it-refresh-the-systray-icons#18038441
GetClientRect(
hNotificationArea = FindWindowEx(
FW(FW(FW(NULL, "Shell_TrayWnd"), "TrayNotifyWnd"), "SysPager"),
NULL,
"ToolbarWindow32",
"Notification Area"),
&r);
for (LONG x = 0; x < r.right; x += 5)
for (LONG y = 0; y < r.bottom; y += 5)
SendMessage(
hNotificationArea,
WM_MOUSEMOVE,
0,
(y << 16) + x);
return 0;
}
Powershell solution, put this in your script
Add-Type -AssemblyName System.Windows.Forms
Add-Type #"
using System;
using System.Runtime.InteropServices;
public struct RECT {
public int left;
public int top;
public int right;
public int bottom;
}
public class pInvoke {
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll")]
public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
public static void RefreshTrayArea() {
IntPtr systemTrayContainerHandle = FindWindow("Shell_TrayWnd", null);
IntPtr systemTrayHandle = FindWindowEx(systemTrayContainerHandle, IntPtr.Zero, "TrayNotifyWnd", null);
IntPtr sysPagerHandle = FindWindowEx(systemTrayHandle, IntPtr.Zero, "SysPager", null);
IntPtr notificationAreaHandle = FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32", "Notification Area");
if (notificationAreaHandle == IntPtr.Zero) {
notificationAreaHandle = FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32", "User Promoted Notification Area");
IntPtr notifyIconOverflowWindowHandle = FindWindow("NotifyIconOverflowWindow", null);
IntPtr overflowNotificationAreaHandle = FindWindowEx(notifyIconOverflowWindowHandle, IntPtr.Zero, "ToolbarWindow32", "Overflow Notification Area");
RefreshTrayArea(overflowNotificationAreaHandle);
}
RefreshTrayArea(notificationAreaHandle);
}
private static void RefreshTrayArea(IntPtr windowHandle) {
const uint wmMousemove = 0x0200;
RECT rect;
GetClientRect(windowHandle, out rect);
for (var x = 0; x < rect.right; x += 5)
for (var y = 0; y < rect.bottom; y += 5)
SendMessage(windowHandle, wmMousemove, 0, (y << 16) + x);
}
}
"#
Then use [pInvoke]::RefreshTrayArea() to reset

Resources