Bypassing Factory Reset Protection Microsoft Lumia 640

The problem:

Recently I had to factory reset my Lumia 640 with Windows 10 Build 15063. However the factory reset protection cannot be turned off in settings. It will ask for password then the slider would stay on.


I proceeded with a factory reset, then I am greeted with the reset protection notification screen (no surprise)


As the back-end service for Windows Mobile has ended, I cannot turn off the protection by tapping Next and logging into my Microsoft Account here, nor could I find my recovery key in the Find My Phone section (only my Surface keys are there) on Microsoft’s web site.


The solution:

Fortunately the recovery key window has a security vulnerability. Tap on one of the five text fields on the recovery key window to bring up the touch keyboard. Long tap the &123 button on the keyboard and then tap the first menu item that looks like a gear (this is actually a security vulnerability similar to how the simplified Chinese version of Windows 2000 let you log in without a password). Now you are in keyboard settings. Tab the gear icon on top left to reach Settings Home.

From Settings Home, go to Update & Security, then go to For Developers, turn on Developer Mode. Turn on Device Portal, make sure Authentication is off. Write down the address under “Connect using”

On your computer, download Windows Phone Interop Tools ( The version I downloaded is 1.9 RC3 because the most recent version has a lot more dependencies to deploy. Extract the downloaded zip file to a folder. Browse the extracted files for a bit and remember where the appx files are.

Visit the Windows Phone Device Portal on your computer using a we browser with the address you wrote down when turning on the Device Portal. The default page would be apps manager, the left pane is Install App, which let you sideload an app.


Under App package, click Choose File and pick the InteropTools.version.xxxxx appx file you downloaded. Under dependency, add the appx files under the dependency folder in extracted files. You would only need to deploy the arm versions of appx files as Lumia 640 has an ARM CPU.


Click Go and wait for the deployment to finish. Then refresh the page. Click the drop down below Installed apps, and select Interop Tools. Click the Start buttom.


On the phone, the interop tools will appear. Launch the Setup Wizard app from there. On my version of Interop Tools, the steps are the following: Tap Next on welcome screens. Then tap on This Device. At the welcome page, tap the hamburger menu button on top left, then in the menu options tree, expand General, then tap Applications. Swipe left on the tabs that begins with Deployment options until you reach Package List. Tap on the Search a Package textbox, and enter wizard. Tab on the search result (the Setup Wizard app).

Now finish the rest of the setup process. It should be complaining about unable to turn on Factory Reset Protection, ignore it and reboot after the finishing the setup wizard. Enjoy!

Posted in Microsoft | Tagged , , , | Leave a comment

New web server hijacker HttpResetModule.dll

Today a friend’s server was hacked. The web site displays normally if visited directly. The content is highjacked when visit from a Baidu Search result, similar to what user 41nbow experienced at

A file system wide search for recent changed files shows that %windir%\system32\inetsrv\config\applicationHost.config file was recently updated. New entries were added to the end of the <globalModules> section. Despite their location being C:\Windows\Microsoft.NET\Framework\v2.0.50727 and C:\Windows\Microsoft.NET\Framework64\v2.0.50727, they bear no Microsoft signature nor any other version information. Also, the file name HttpResetModule is suspicious, why a web server want do reset a connection?

Removing the modules from IIS manager stopped the hijack, but how they are dropped there need further investigation. There is also a C:\Program Files (x86)\Google\svchost.exe that claims to be a 360 Safeguard executable, which is obviously an imposter.

When I began writing only 2 providers flagged the ISAPI module files as malicious on VirusTotal. When I finished writing, 2 more providers flagged them as malicious. That was quick.

Posted in Uncategorized | Leave a comment

Better Late Than Never

This post originally appeared on Joycode on Sept 17 2004.



关于如何设置文件夹视图的显示方式的问题,Paul DiLascia在他的MSDN杂志C++Q&A专栏中提供了另一个解决方案。参见
List View Mode, SetForegroundWindow, and Class Protection(。PS:这家伙又用Spy++大法……

浏览器控件显示文件夹视图(例如本地目录或者FTP站点)时在其中双击目录,选中的目录会用新的资源管理器窗口打开的问题,是因为浏览器控件中的文件夹视图在打开文件夹的时候并不触发浏览器的NewWindow2事件,而是调用ShellExecuteEx,用DDE的方式和Shell通讯。微软知识库文章Q189634 WebApp.exe Enables User to Move WebBrowser Ctrl(描述了如何处理这样的DDE会话。呃……顺便说一下,这篇文章文不对题……


#define WM_GETISHELLBROWSER (WM_USER+7)//差不多一年过去了,这个消息还是a yet-to-be documented message

void CCustomFileDialog::OnInitDone()
//Remember, when you customize the open file dialog,
//your CFileDialog is actually a child of the real dialog,
//which explains why you must use GetParent.
//(For details see article “Give Your Applications the Hot New Interface Look with Cool Menu Buttons”
//in the January 1998 issue of C++Q&A, MSJ.)

// WARNING! Although this is a non-intrusive customization,
// it does rely on unpublished (but easily obtainable)
// information. The Windows common file dialog box implementation
// may be subject to change in future versions of the
// operating systems, and may even be modified by updates of
// future Microsoft applications. This code could break in such
// a case. It is intended to be a demonstration of one way of
// extending the standard functionality of the common dialog boxes.
m_pSB=(IShellBrowser *)GetParent()->SendMessage(WM_GETISHELLBROWSER,0,0);

//To control the folder view of the webbrowse control (e.g. in CHTMLView),
//send this message to it and get its IShellBrowser interface.
//in CMyHTMLView::OnDocumentComplete()
// m_pSB=(IShellBrowser *)GetDlgItem(AFX_IDW_PANE_FIRST)->SendMessage(WM_GETISHELLBROWSER,0,0);
//if you create your webbrowser control manually as follows
//extern CWnd m_wndBrowser;
//m_wndBrowser.CreateControl(CLSID_WebBrowser, lpszWindowName,
//   WS_VISIBLE | WS_CHILD, rectPosition, pwndParent, nChildID))
//then send message like this
//m_pSB=(IShellBrowser *)m_wndBrowser.SendMessage(WM_GETISHELLBROWSER,0,0);


为了偷懒,我的代码基于微软知识库文章Q195034 HOWTO: OfnKing Demonstrates CFileDialog Customization (的代码,增加了一个全选按钮,在按钮的响应函数中编写了下面的代码选择文件夹视图中的全部文件。如果操作系统是WindowsXP,还同时切换到缩略图视图。

//If you don’t have VS.NET, you need to download Platform SDK:
#define GetPIDLFolder(pida) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[0])
#define GetPIDLItem(pida, i) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[i+1])
//a similar ILIsFolder function is included in the sample code of my article
//”Folder Thumbnail View Using Virtual List and Custom Draw” //
      BOOL bRet=FALSE;
      LPCITEMIDLIST  pidlChild=NULL;
      IShellFolder* psf=NULL;
      HRESULT    hr = SHBindToParent(pidl, IID_IShellFolder, (LPVOID*)&psf, &pidlChild);
      if (SUCCEEDED(hr) && psf)     {
          if (SUCCEEDED(hr))         {
              //in file system, but is not a folder
              if( (~rgfInOut&SFGAO_FOLDER) && (rgfInOut&SFGAO_FILESYSTEM) )
      return bRet;
void CCustomFileDialog::OnSelectAll() {
      if(m_pSB&&m_bMulti&&m_bExplorer)//Using IShellBrowser to Communicate with folder view
          IShellView  * pIShellView  =NULL;
          LPMALLOC pMalloc = NULL;
          IDataObject* pIDataObject=NULL;
          IFolderView* pFolderView=NULL;
          FORMATETC fmte;
          STGMEDIUM stgmedium ;
          ZeroMemory( (LPVOID)&fmte, sizeof(STGMEDIUM) );
          ZeroMemory( (LPVOID)&fmte, sizeof(FORMATETC) );
          fmte.tymed = TYMED_HGLOBAL;
          fmte.lindex = -1;
          fmte.dwAspect = DVASPECT_CONTENT;
          fmte.cfFormat = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
         LPITEMIDLIST pidlFull=NULL;
              HRESULT hr=m_pSB->QueryActiveShellView(&pIShellView);
              if(pFolderView)//change view mode
              hr=::SHGetMalloc(&pMalloc); //Get pointer to shell alloc
              hr=pIShellView->GetItemObject(SVGIO_ALLVIEW ,IID_IDataObject,(LPVOID*)&pIDataObject);
              LPIDA pida = (LPIDA) GlobalLock(stgmedium.hGlobal);
              if (pida)
                  LPCITEMIDLIST    pidlFolder=GetPIDLFolder(pida);
                  for(UINT i=0;i<pida->cidl;i++)
                      //filter folders
                      LPCITEMIDLIST pidl=GetPIDLItem(pida,i);
                  //Move focus to the folder view so that
                  //the selected items show properly
          //Clean up

Posted in Uncategorized | Leave a comment

Converting generic OopFactory.X12 structures to typed counterparts

OopFactory.X12 can parse EDI messages into segments and loops. However despite typed segments and loops exist, the parser does not generate them in the object model.  The unit test only use them when generating EDI messages.

The typed segments and loops are aggregative objects that do not contain their own data members besides the contained untyped objects. Which means if I replace the contained object with the generic one from the parser via .Net reflection, then I can access the object model in a typed way. So I created this in a static class

public static void SetFieldValue(this object obj, string name, object value)
             // Set the flags so that private and public fields from instances will be found
             var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
             var field = obj.GetType().GetField(name, bindingFlags);
             field.SetValue(obj, value);
public static T AsTypedSegment<T>(this OopFactory.X12.Parsing.Model.Segment segment)
             where T: OopFactory.X12.Parsing.Model.TypedSegment,new()

             if (segment == null) return null;
             T result = new T();
             result.SetFieldValue(“_segment”, segment);
             return result;
public static T AsTypedLoop<T>(this OopFactory.X12.Parsing.Model.Loop loop)
             where T : OopFactory.X12.Parsing.Model.TypedLoop, new()

             if (loop == null) return null;
             T result = new T();
             result.SetFieldValue(“_loop”, loop);
             return result;

Then I use them to convert the generic segments and loops from the parser to typed ones. The example is for parsing a 835 file, for other types the loop numbers and segments may be different.

string fileText = System.IO.File.ReadAllText(fileName);
List<Interchange> envelopes = parser.ParseMultiple(fileText);
if (envelopes.Count == 0) return null;

var isa = envelopes[0];

var gs = isa.FunctionGroups.ElementAt(0);

var st = gs.Transactions[0];

var payerLoops = st.Loops.Where(l => l.Specification.LoopId.Equals(“1000A”));

var payerLoop = payerLoops.FirstOrDefault();
var payerName = payerLoop.AsTypedLoop<TypedLoopN1>().N102_Name;

var payerIdSegment = payerLoop.Segments
                     .Where(s => s.SegmentId.Equals(“REF”)
                         && s.GetElement(1).Equals(“2U”)).FirstOrDefault();
if (payerIdSegment != null)
          var payerId = payerIdSegment.AsTypedSegment<TypedSegmentREF>().REF02_ReferenceId;

var paymentLoops = st.Loops.Where(l => l.Specification.LoopId.Equals(“2000”));

foreach (var paymentLoop in paymentLoops)

        var claimPaymentInformationLoops = paymentLoop.Loops.
                         Where(l => l.Specification.LoopId.Equals(“2100”));

       foreach (var claimPaymentInformationLoop in claimPaymentInformationLoops)
                var mrnSegment = claimPaymentInformationLoop.Segments.Where
                           (s => s.SegmentId.Equals(“REF”) && s.GetElement(1).Equals(“EA”)).FirstOrDefault()
                  if (mrnSegment != null)
                             var patientMrn = mrnSegment.REF02_ReferenceId;

The library is written for 837, thus many types used in 835 like loop 2000 and segment CLP are not defined.

Posted in Uncategorized | Leave a comment

How To Determine When a Page Is Done Printing in WebBrowser Control

Note this post is originally written in 2012. It was lost when moving my web site from Windows Live Spaces to WordPress. I found a dead link to my web site on Stackoverflow and found an archive from So here it is the old article, with dead link updated of course.

The printing from a WebBrowser control can be customized by using custom headers and footers (, archived from or replacing the default print template. However, using such techniques conflicts with the PRINT_WAITFORCOMPLETION flag, which is used for synchronous printing.

Since Internet Explorer 6.0, the WebBrowser control raises the DWebBrowserEvents2::PrintTemplateTeardown event when a print template has been destroyed. If the printing involves a custom print template, this is a good indicator of print completion. You can create a event handler function in your application for this event to determin if a the WebBrowser control is finished printing a Web page.


The WebBrowser control launches another thread which hosts another MSHTML document which renders to the printer. When this thread is finished, if a custom print template is involved, the WebBrowser control destroys the print template and raises PrintTemplateTeardown event. This indicates that the WebBrowser control has completed printing the Web page.

If the default print template and the customization of headers and footers are desired, load the template from the source of IExplorer.exe, and use it as a custom template.

To translate the asynchronous printing to synchronous, a message loop need to be created (better if use with a timeout handler) .

BOOL PrintTemplateTeardownFired=FALSE;
//launch printing……
//loop until PrintTemplateTeardown is set to TRUE in the PrintTemplateTeardown event handler
MSG msg;
while (!PrintTemplateTeardownFired&&GetMessage(&msg, NULL, 0, 0) > 0)


Posted in Uncategorized | Leave a comment

Troubleshooting a memory leak

Got called into a memory leak troubleshooting. The application was leaking memory at 1mb per second. In memory profiler, most of the growing memory are used by byte[] and RuntimeMethodHandle (growing at around a million per minute). Initially I thought it is a disposing problem, but the memory occupied by disposable objects does not increase over time.

Looking at the RuntimeMethodHandle instances, I found that it is closely associated with DynamicResolver, whose instance count grows in a much smaller but steady rate. This leads me to kissdodog’s post Windbg + .Net .NET Memory Profiler 排查内存泄露 but kissdodog only located the problem but didn’t give a cause (some coworker got the blame and fixed it).

Then I want to see if there’s any GDI leak and added handle columns to task manager, surprisingly there’s a handle leak growing at 1/2 per second, but then there is no memory map in the code. Under Process Explorer’s handle view,  the leaking handles are revealed as user tokens, which is even more puzzling because the code doesn’t deal with windows logins. But at least this gives me some clear indicator to divide and conquer.

By commenting out portions of code (more like a human binary search) and watching Task Manager religiously, I found the issue is caused by creating XslCompiledTransform in a loop, something KB316775 cited as a design limitation that the dynamic assemblies can’t be unloaded. Obviously this isn’t fixed even in .Net 4.8. The KB was no longer published by Microsoft and I had to read it off a mirror.

Once the problem is located the fix is easy, making those XslCompiledTransform objects singleton solved the issue.

Posted in Uncategorized | Leave a comment

Icepocalypse 2021 冰狱 2021

this is my dairy about the winter storm occurred in Feb 2021.


Feb 13 Sat. 27-30F. Stockpile food (glad I did it). Heard ice building on roads, so instead I shopped on foot. Almost fell because of invisible ice.

2月13日周六 –3-1度。储粮(幸好我这么做了)。听说路上在结冰所以我走路去买菜。还是有看不见的冰,差点摔倒。

Feb 14 Sun. 12-30F Stay home. Freeze warning, keep water dropping. Listened to police radio for a while and heard nothing but crashes. Person is bleeding on Colorado Hills… that is why we advise everyone (to stay off road)…. several vehicles… we need a tow at…. some of the ten fours sound like sigh and two person exchanging (insurance) info was almost a relief. It snowed the night and sounded like raining cats and dogs.

2月14日周日 –11–1度。宅。冰冻警报,保持水龙头滴水。收听了一下警察的通话,基本上都是车祸。科罗拉多丘有人流血。这就是为什么我们建议所有人(不上路)——多辆车——我们这里需要拖车——很多10-4(警用代码,意即收到)听起来像叹气。两个人交换(保险)信息几乎是好消息。晚上下雪的声音听起来像冰雹。

Feb 15 Mon 10-27F. Snow. Wake up by UPS beeps. Turned it off and woke up again by chilling. Realized the power outage could last for a while, announced my unavailability to coworkers. Then saw this outside

2月15日周一 –13–5度。下雪。被不间断电源吵醒。关掉之后回笼觉,又被冻醒。意识到停电可能会很久,通知同事我一时半会不能上班。然后看到外面是这样


Went out for some warm food. Big mistake. 4-10 inches of snow and sometimes step on curbs. Wandering dogs. HEB and everything else closed. No cell signals most of the way. Good that almost nobody is driving and for the rest they drive really slow. And snow blindness is a thing.



Power briefly went back for about an hour after 3pm. but that is just enough for cooking and charging power banks.



Feb 16 Tue 6-25F. Cloudy. Room temperature dropped so much that my dog was crying. So took her to the warmest place in the room.

2月16日周二 –13–4度。多云。室温降到狗狗都在哭了,所以把她移动到房间里最温暖的地方。


and dress her with a cut rice bag



Power back again after 3pm for 40 minutes. Cooked and charged.


Started refreshing ERCOT web site. The 60KMW goal was never reached, only briefly touched 50KMW.

开始刷德州电力可靠委员会(ERCOT )网站。60吉瓦的恢复目标当天没达到,仅仅短暂地达到了50吉瓦

Feb 17 Wed. 23-32F. Snow. From the ERCOT report, the grid almost crashed in the morning with almost no margin between generation and load. Generation picked up in the afternoon to 55KMW but power didn’t come back at all today. Did some cleanup, help neighbor and got helped by a neighbor with a hammer.



Pipe started to burst everywhere and I lost water today.


Feb 18 Thu. 19-32F. Snow. Slept up early yesterday and woke up at 1am. Then saw this:



Brightest night in years.


Power went back on around 2 am. The ERCOT price map is almost green now, with a small deep blue spot indicating negative power prices near Houston. But without water I can no longer cook. Decided to get some water from HEB. My car was actually frozen up like this



So I decided to take a bus which is running for the first time since Monday. The trees along the way are down by the snowstorm:



They looked like this in the summer



On the way there was a pond



I wonder where the ducks went. And this was the pond in the summer



At HEB there’s a long line… and thick ice.



Someone actually fell and one helping on the left almost fell too when running over.



Got in after an hour of waiting in line. Unfortunately there was no waster or milk on the shelf. Settled for some juice and soymilk.


Icicle fell off and scared a bus rider. But it is a good sign that ice was melting.


My apartment offered its pool water for toilet use. Nice for them.


ERCOT reports 60KMW generation for the first time and the price map is sky blue, means everything normal again.


Posted in Uncategorized | Leave a comment



用了Process Monitor跟踪了一下,发现每次切换中英文的时候,微软拼音都会在%appdata%\Microsoft\InputMethod\Chs下面创建一个名字为UDPXXXX(这里XXXX是16进制数字).tmp的文件,我这个目录下有六万五千多个这样的文件。从命名风格来看,很明显是在调用GetTempFileName,而这个函数有65535个文件的限制,不删除文件的话,第65536次调用会失败,应该是微软拼音没有处理好调用这个函数失败的情况,也没有删除临时文件的代码,就卡住了。


del %appdata%\Microsoft\InputMethod\Chs\*.tmp /q



Posted in Uncategorized | Leave a comment

Today’s fake email of the day

Today’s fake email of the day

Hi Dear,

How are you doing hope you are fine and OK?

I was just going through the Internet search when I found your email address


So you care about an article titled “
Trap CtrlAltDel; Hide Application in Task List on Win2000/XP” in 2020 and downloaded its source code, but still don’t know my name?

Also when I read the message header (it is called view source in hotmail or view original in gmail)
From: Lisa Williams
X-Mailer: WebService/1.1.16718 YMailNodin Mozilla/5.0 (Windows NT 6.1; rv:81.0) Gecko/20100101 Firefox/81.0
Content-Length: 572
X-IncomingHeaderCount: 14
To: Undisclosed recipients:;

So this is a bulk mail, I am BCCed. Kinda strange to do for a letter that express love interest. But Kudos to keep your Firefox version up to date! Although the scammer can lie here too if wanted to just like everywhere else, there is nothing really beneficial to say you mailed it from Microsoft Outlook Express.

Also in the mail header:

Received-SPF: SoftFail ( domain of transitioning discourages use of as permitted sender)

I wonder why…

Posted in Uncategorized | Leave a comment

Finding the right ruby version

I am installing eHMP on Centos 7. Centos 7 has ruby 2.0 out of box, thus the install

chef-client -o workstation –config ~/Projects/vistacore/.chef/knife.rb

fails with

rb-notify version 0.10.0 needs Ruby 2.2.2 or newer

Following the instructions at I got ruby 2.7 installed. However

sudo chef-client -o workstation –config ~/Projects/vistacore/.chef/knife.rb

fails with the same error.


ruby –version

shows that rvm has no effect on sudo. I am still running the script against Ruby 2.0

Supposedly I can sudo and install rvm there, but rvm complained and suggested me to use rvmsudo instead. Then I tried it, rvmsudo doesn’t carry over my environment, even $HOME, thus the script still fails.

After searching for awhile I found a walkaround

rvmsudo bash -c “HOME=$HOME; exec bash” chef-client -o workstation –config ~/Projects/vistacore/.chef/knife.rb

This gets the home directory passed to the script, now the script is complaining

STDERR: ERROR:  While executing gem … (OptionParser::InvalidOption) invalid option: –no-rdoc

The script was pretty old, I know. I have no time to fix the script, so I need to downgrade the ruby version. After testing for each version I settled for 2.3.

rvm install 2.3

rvm use 2.3 –default

sudo gem update –system 2.3

Now the script runs successfully.

Posted in eHMP | Tagged | Leave a comment