The MASM Forum

Toddler's Corner => Romper Room => Topic started by: jj2007 on October 18, 2019, 12:47:53 PM

Title: How complicated is the code for Microsoft Windows?
Post by: jj2007 on October 18, 2019, 12:47:53 PM
https://www.quora.com/How-complicated-is-the-code-for-Microsoft-Windows

Quote
How complicated is the code for Microsoft Windows?

So complicated that Microsoft can’t fix it.

This is old (2006), so it only counts as the type of thing Microsoft seems to put out.

This is a linux call trace for apache on Linux.

(https://qph.fs.quoracdn.net/main-qimg-d60759c21f39b4074a5136dbc7c239dd)

This is a call trace for Microsoft IIS…

(https://qph.fs.quoracdn.net/main-qimg-0286ae0b47db36783b68632de12256ee.webp)
Title: Re: How complicated is the code for Microsoft Windows?
Post by: Raistlin on October 18, 2019, 04:10:52 PM
<expletive> Fark <expletive> WOW <expletive>  Jesu... <expletive> 
Thanks JJ - it all makes sense now......
Title: Re: How complicated is the code for Microsoft Windows?
Post by: hutch-- on October 18, 2019, 05:07:58 PM
 :biggrin:

While I do appreciate the humour, the odd Microsoft code I have seen from long ago was clean, tidy, properly formatted and fully commented. For an OS that has been running for so long while maintaining a reasonable level of backwards compatibility, it has the obvious problems of some old architecture that has had to be kept alive so that people could still run their old software. 16 bit MS_DOS executables would still run on XP and early 32 bit NT4 apps will generally still run on Win10.

Now contrast this with an Apple MAC or any flavour of Linux and you will have the semantic problem of "what is backward" and "what is compatible" as each new OS version requires the software to be re-compiled or in Apple's case, dumped and you buy a new MAC.

While I have not been without complaint about Microsoft changing the rules in each OS version, better the devil you know than the alternative.
Title: Re: How complicated is the code for Microsoft Windows?
Post by: jj2007 on October 18, 2019, 11:54:16 PM
Hutch,

You are right. I've wasted an incredible amount of time chasing Micros**t "features", but Linux seems even more confused than Windows. Somewhere I read that there isn't one Linux, there are rather 300+ different Linuxes. And it's true that even very, very old Windows programmes run smoothly on Win10, especially if they are built with Masm32 :badgrin:
Title: Re: How complicated is the code for Microsoft Windows?
Post by: AW on October 19, 2019, 01:57:24 AM
Most of this propaganda is very dated and Linux people will never update their beliefs.
Linux is very likely full of traps and backdoors deeply entrenched into the kernel:
https://thehackernews.com/2019/10/linux-sudo-run-as-root-flaw.html
Title: Re: How complicated is the code for Microsoft Windows?
Post by: daydreamer on October 19, 2019, 11:48:38 PM
https://www.quora.com/How-complicated-is-the-code-for-Microsoft-Windows

Quote
How complicated is the code for Microsoft Windows?

So complicated that Microsoft can’t fix it.

This is old (2006), so it only counts as the type of thing Microsoft seems to put out.

This is a linux call trace for apache on Linux.

(https://qph.fs.quoracdn.net/main-qimg-d60759c21f39b4074a5136dbc7c239dd)

This is a call trace for Microsoft IIS…

(https://qph.fs.quoracdn.net/main-qimg-0286ae0b47db36783b68632de12256ee.webp)
OMG,thats what happening inside IIS I am currently running
and I had no idea there was loads of patches in A lot of Patches(Apache)  :greenclp:
Title: Re: How complicated is the code for Microsoft Windows?
Post by: TimoVJL on October 20, 2019, 01:40:25 AM
diagram of C versus C++ ?
Title: Re: How complicated is the code for Microsoft Windows?
Post by: morgot on January 26, 2020, 02:46:25 AM
WinApi is very difficult (versus linux api)
in linux we have very simple , such as open,mmap - functions with 2-3 parametres. In windows we have terrible winapi functions with 1000 parametres, most of them are usually NULL (security attributes and other). Copmare exec and CreateProcess, open and CreateFile.. i don't tell about security api (InitializeAndAllocateSomeSid (p1,...p21)) or COM! :eusa_boohoo:

Winapi written by drug-users..
Title: Re: How complicated is the code for Microsoft Windows?
Post by: hutch-- on January 26, 2020, 03:06:58 AM
He he, while I run this forum on a Linux server and recently built a 64 bit Linux file server for local networking, I still find Linux a crude imitation of a desktop. As a Web server its fine but its only recently that you can get a distro that has a presentable desktop where you can actually find anything. The Mint Linux team have almost civilised Linux.

As usual if you need to do anything useful its,

sudo su enter
password enter

Then you have to go looking for what you are after. Then you get directories that start with a period that don't show so you have to go exploring to find it. This is 1986 all over again, ancient junk that has not changed in 30 years, OCTAL file permissions and the like. Microsoft Windows for all of its many warts is navigatable and the information to write software is findable from help files and MSDN. Getting anything useful in Linux is an internet search and then you run into DISTRO-LAND with all of its variations.

With Windows the tech reference is many levels deep, with Linux it is splashed all over the internet like a mad woman's sewerage with very little depth. As a server Linux is fine but as a desktop its far behind Windows and while a few distros like Ubuntu and Mint Linux are catching up, there is still a long way to go.
Title: Re: How complicated is the code for Microsoft Windows?
Post by: morgot on January 26, 2020, 03:22:46 AM
As a server Linux is fine but as a desktop its far behind Windows and while a few distros like Ubuntu and Mint Linux are catching up, there is still a long way to go.
Yes, I agree this.  Windows is more comfy for people. But in coding...COM is terrible, no api in linux are so complicated
Title: Re: How complicated is the code for Microsoft Windows?
Post by: AW on January 26, 2020, 03:34:44 AM
As a server Linux is fine but as a desktop its far behind Windows and while a few distros like Ubuntu and Mint Linux are catching up, there is still a long way to go.
Yes, I agree this.  Windows is more comfy for people. But in coding...COM is terrible, no api in linux are so complicated
COM is terrible from ASM and from C/C++.
It is easy from Delphi and also from the .Net languages. It was possible to produce fast an ActiveX control in Visual Basic 6, but VB is dead long ago.
We should not try to understand in detail how it works, we will never get it because COM was imagined from the ground up to be a barrier. There are others like RPC.

Rule: Don't try to understand in detail, you will never get it, just learn how to obtain results.
Title: Re: How complicated is the code for Microsoft Windows?
Post by: jj2007 on January 26, 2020, 04:42:11 AM
COM looks a bit complicated at first, but the most difficult part is finding and creating the GUIDs and STRUCTs. Once you have that, it's no more difficult than ordinary WinAPI invokes. See e.g. Erol's SetWallpaper example (http://masm32.com/board/index.php?topic=6483.msg72338#msg72338). And COM is really well documented.
Title: Re: How complicated is the code for Microsoft Windows?
Post by: AW on January 26, 2020, 04:59:38 AM
People that brag about easiness try to be smart but have not the slightest idea of the whole mess that COM is, recognized by almost everybody, and are still in the

(https://www.dropbox.com/s/kg9jtif3606pu33/petzold.png?dl=1)

era.
Title: Re: How complicated is the code for Microsoft Windows?
Post by: jj2007 on January 26, 2020, 05:23:55 AM
What's wrong with you, José Pascoa? Why do your posts inevitably contain insults? Why is it not possible to have a normal conversation with you?
Title: Re: How complicated is the code for Microsoft Windows?
Post by: AW on January 26, 2020, 05:31:37 AM
I am not insulting JJ2007, show me a COM Server or an ActiveX control you have done with your "pure" Masm (which is a closed source library called from macros.)

MasmBasic pure MASM:
Code: [Select]
LibTmp\LibTmpBG.obj    _MbFindPro@0
LibTmp\LibTmpBG.obj    _MbPDat@0
LibTmp\LibTmpBF.obj    _MbTestRet@0
LibTmp\LibTmpBF.obj    _MbVI@12
LibTmp\LibTmpBF.obj    _txViStrings
LibTmp\LibTmpBE.obj    _MbPS
LibTmp\LibTmpBE.obj    _MbPrintRtf@4
LibTmp\LibTmpBE.obj    _ReRgP@16
LibTmp\LibTmpBD.obj    _MbSpriteP
LibTmp\LibTmpBD.obj    _MbSpriteTable
LibTmp\LibTmpBD.obj    _MbWarp@20
LibTmp\LibTmpBD.obj    _SprBuffer
LibTmp\LibTmpBC.obj    _MbPoly3
LibTmp\LibTmpBC.obj    _MbSinP@0
LibTmp\LibTmpBB.obj    _GuiSMP@4
LibTmp\LibTmpBB.obj    _MbGetLG@0
LibTmp\LibTmpBB.obj    _MbTBar@16
LibTmp\LibTmpBB.obj    _cbRN@16
LibTmp\LibTmpBB.obj    _tbs0
LibTmp\LibTmpBA.obj    _InsJb@12
LibTmp\LibTmpBA.obj    _LineCountP@0
LibTmp\LibTmpAZ.obj    _MbUZ@8
LibTmp\LibTmpAZ.obj    _xzmb
LibTmp\LibTmpAY.obj    _CanvasInfo
LibTmp\LibTmpAY.obj    _MbArrayPlot@28
LibTmp\LibTmpAY.obj    _MbDBM@8
LibTmp\LibTmpAY.obj    _MbDbGetRgn@8
LibTmp\LibTmpAY.obj    _MbGetMapIndex@0
LibTmp\LibTmpAY.obj    _apStruct
LibTmp\LibTmpAX.obj    _MbXls@8
LibTmp\LibTmpAX.obj    _xlsServer$
LibTmp\LibTmpAW.obj    _MbDlgP@16
LibTmp\LibTmpAV.obj    _MbArrSort@16
LibTmp\LibTmpAU.obj    _MbwInputStrP@8
LibTmp\LibTmpAT.obj    _MbQSortP@8
LibTmp\LibTmpAT.obj    _MbStrCmp@12
LibTmp\LibTmpAT.obj    _QsMode
LibTmp\LibTmpAS.obj    _GdiSI
LibTmp\LibTmpAS.obj    _GdiStatus$
LibTmp\LibTmpAS.obj    _GetEncoderCLSID@4
LibTmp\LibTmpAS.obj    _GuiNeedsPaint
LibTmp\LibTmpAS.obj    _ImgPaintP@12
LibTmp\LibTmpAS.obj    _MbGdiInit@0
LibTmp\LibTmpAS.obj    _gdiSmoothing
LibTmp\LibTmpAS.obj    _hCanvas4Image
LibTmp\LibTmpAR.obj    _MbFlipP@0
LibTmp\LibTmpAQ.obj    _MbMD5@12
LibTmp\LibTmpAQ.obj    _MbRk64
LibTmp\LibTmpAQ.obj    _RegKeyP@16
LibTmp\LibTmpAP.obj    _MbWinGh@0
LibTmp\LibTmpAO.obj    _MbLMR@12
LibTmp\LibTmpAO.obj    _MbTrim@8
LibTmp\LibTmpAO.obj    _MbUpperLowerP@8
LibTmp\LibTmpAO.obj    _Mb_SCB@0
LibTmp\LibTmpAN.obj    _MbSound@0
LibTmp\LibTmpAN.obj    _MouseKeys@0
LibTmp\LibTmpAN.obj    _NoTagP@0
LibTmp\LibTmpAN.obj    _PromptWM@0
LibTmp\LibTmpAN.obj    _wcxP$
LibTmp\LibTmpAM.obj    _StringFill@0
LibTmp\LibTmpAL.obj    _MbUtf8@0
LibTmp\LibTmpAL.obj    _MsgTableP@12
LibTmp\LibTmpAL.obj    _wDataP@0
LibTmp\LibTmpAK.obj    _Float2Asc@12
LibTmp\LibTmpAK.obj    _MbBufferFix@0
LibTmp\LibTmpAK.obj    _MbBufferGet@0
LibTmp\LibTmpAK.obj    _MbBufferInit@0
LibTmp\LibTmpAK.obj    _MbExp@0
LibTmp\LibTmpAK.obj    _MbFloatCmp@0
LibTmp\LibTmpAK.obj    _MbFpuStatusP@0
LibTmp\LibTmpAK.obj    _MbGetSlotPointer@0
LibTmp\LibTmpAK.obj    _MbLoadRich@0
LibTmp\LibTmpAK.obj    _MbVal@12
LibTmp\LibTmpAK.obj    _RichEditUsed
LibTmp\LibTmpAK.obj    _pcTable
LibTmp\LibTmpAJ.obj    _MbLaMs
LibTmp\LibTmpAJ.obj    _ShellWait@16
LibTmp\LibTmpAJ.obj    _WriteData@8
LibTmp\LibTmpAJ.obj    _lsp
LibTmp\LibTmpAI.obj    _ClearLocalsP@0
LibTmp\LibTmpAI.obj    _MbStackB@0
LibTmp\LibTmpAH.obj    _MbBinP@0
LibTmp\LibTmpAH.obj    _MbHexP@8
LibTmp\LibTmpAH.obj    _MbMulQQ@8
LibTmp\LibTmpAH.obj    _R10ToX@0
LibTmp\LibTmpAH.obj    _R16ToST@0
LibTmp\LibTmpAH.obj    _qmFuncs
LibTmp\LibTmpAH.obj    _qmP@0
LibTmp\LibTmpAG.obj    _ExtractP@24
LibTmp\LibTmpAG.obj    _InstrCi@16
LibTmp\LibTmpAG.obj    _MbFileCmp@12
LibTmp\LibTmpAG.obj    _isCurPos
LibTmp\LibTmpAF.obj    _DtFormat
LibTmp\LibTmpAF.obj    _FindInFile@20
LibTmp\LibTmpAF.obj    _GfDateTimeP@8
LibTmp\LibTmpAF.obj    _MbDTF@8
LibTmp\LibTmpAF.obj    _MbGetFileCount
LibTmp\LibTmpAE.obj    _MbCopy@12
LibTmp\LibTmpAE.obj    _MbCopyz@8
LibTmp\LibTmpAD.obj    _MbCol@0
LibTmp\LibTmpAD.obj    _MbColCust
LibTmp\LibTmpAD.obj    _MbFnt@8
LibTmp\LibTmpAD.obj    _MbWinStrP@8
LibTmp\LibTmpAC.obj    _ArrSearchP@0
LibTmp\LibTmpAC.obj    _Browse4Folder@16
LibTmp\LibTmpAC.obj    _FileReadP@4
LibTmp\LibTmpAC.obj    _MbClose@0
LibTmp\LibTmpAC.obj    _MbD2m
LibTmp\LibTmpAC.obj    _MbExistP@0
LibTmp\LibTmpAC.obj    _MbGetCL@0
LibTmp\LibTmpAC.obj    _MbGetFileLen@4
LibTmp\LibTmpAC.obj    _MbInputP@0
LibTmp\LibTmpAC.obj    _MbOpenFile@20
LibTmp\LibTmpAC.obj    _MbResString@0
LibTmp\LibTmpAC.obj    _MbStrLen@0
LibTmp\LibTmpAC.obj    _MbStrLenW@0
LibTmp\LibTmpAC.obj    _Open_for_input@12
LibTmp\LibTmpAC.obj    _Open_for_output@12
LibTmp\LibTmpAC.obj    _RecallP@16
LibTmp\LibTmpAC.obj    _StoreHead$
LibTmp\LibTmpAC.obj    _StoreP@12
LibTmp\LibTmpAC.obj    _TclCatch1
LibTmp\LibTmpAC.obj    _TclTry1
LibTmp\LibTmpAC.obj    _TouchP@8
LibTmp\LibTmpAC.obj    _isUtf8P@0
LibTmp\LibTmpAC.obj    _ofSQ@0
LibTmp\LibTmpAC.obj    _txFrl
LibTmp\LibTmpAC.obj    _txRNF
LibTmp\LibTmpAB.obj    _GetNumID@0
LibTmp\LibTmpAB.obj    _GetStringID@0
LibTmp\LibTmpAB.obj    _IsRichP@0
LibTmp\LibTmpAB.obj    _JJ
LibTmp\LibTmpAB.obj    _LetEndPos
LibTmp\LibTmpAB.obj    _LocateP@0
LibTmp\LibTmpAB.obj    _MbAR@0
LibTmp\LibTmpAB.obj    _MbAddToHeapTable@0
LibTmp\LibTmpAB.obj    _MbAllocP@0
LibTmp\LibTmpAB.obj    _MbArGetCTH
LibTmp\LibTmpAB.obj    _MbArGetErased
LibTmp\LibTmpAB.obj    _MbArrayDim@8
LibTmp\LibTmpAB.obj    _MbArrayErase@0
LibTmp\LibTmpAB.obj    _MbArrayGet@8
LibTmp\LibTmpAB.obj    _MbArraySwap@0
LibTmp\LibTmpAB.obj    _MbClipP@0
LibTmp\LibTmpAB.obj    _MbDimStruct@12
LibTmp\LibTmpAB.obj    _MbErrAddLine
LibTmp\LibTmpAB.obj    _MbErrTMS
LibTmp\LibTmpAB.obj    _MbError0
LibTmp\LibTmpAB.obj    _MbError1
LibTmp\LibTmpAB.obj    _MbError10
LibTmp\LibTmpAB.obj    _MbError2
LibTmp\LibTmpAB.obj    _MbError3
LibTmp\LibTmpAB.obj    _MbError5
LibTmp\LibTmpAB.obj    _MbError6
LibTmp\LibTmpAB.obj    _MbErrorBuffer
LibTmp\LibTmpAB.obj    _MbFreeP@0
LibTmp\LibTmpAB.obj    _MbGetKeyP@0
LibTmp\LibTmpAB.obj    _MbHeap16@0
LibTmp\LibTmpAB.obj    _MbInputStrP@8
LibTmp\LibTmpAB.obj    _MbInsNum@8
LibTmp\LibTmpAB.obj    _MbInsert@0
LibTmp\LibTmpAB.obj    _MbLenTable
LibTmp\LibTmpAB.obj    _MbNewP
LibTmp\LibTmpAB.obj    _MbPrint@0
LibTmp\LibTmpAB.obj    _MbRegs32
LibTmp\LibTmpAB.obj    _MbReplPrep@16
LibTmp\LibTmpAB.obj    _MbRs@0
LibTmp\LibTmpAB.obj    _MbSAP@0
LibTmp\LibTmpAB.obj    _MbSCP@0
LibTmp\LibTmpAB.obj    _MbSleep@0
LibTmp\LibTmpAB.obj    _MbStdIn@0
LibTmp\LibTmpAB.obj    _MbStdOut@0
LibTmp\LibTmpAB.obj    _MbStringErase@0
LibTmp\LibTmpAB.obj    _MbStructCopy@0
LibTmp\LibTmpAB.obj    _MbStructErase@4
LibTmp\LibTmpAB.obj    _MbTxt2Dw@16
LibTmp\LibTmpAB.obj    _MbwRec@0
LibTmp\LibTmpAB.obj    _NewStrP@0
LibTmp\LibTmpAB.obj    _StreamFromPtr@16
LibTmp\LibTmpAB.obj    _StreamFromPtrP@16
LibTmp\LibTmpAB.obj    _TestRetVal@0
LibTmp\LibTmpAB.obj    _txFatal
LibTmp\LibTmpAA.obj    _Cr$
LibTmp\LibTmpAA.obj    _CrLf$
LibTmp\LibTmpAA.obj    _CrLf_txt
LibTmp\LibTmpAA.obj    _DebFile$
LibTmp\LibTmpAA.obj    _DllTable
LibTmp\LibTmpAA.obj    _Dw2BinBuffer
LibTmp\LibTmpAA.obj    _Dw2BinTable
LibTmp\LibTmpAA.obj    _EspGlob
LibTmp\LibTmpAA.obj    _FifHandle
LibTmp\LibTmpAA.obj    _FifRetBuf
LibTmp\LibTmpAA.obj    _Lf$
LibTmp\LibTmpAA.obj    _MbArrEmpty
LibTmp\LibTmpAA.obj    _MbArrTable
LibTmp\LibTmpAA.obj    _MbBufferStart
LibTmp\LibTmpAA.obj    _MbBytes2Write
LibTmp\LibTmpAA.obj    _MbCF
LibTmp\LibTmpAA.obj    _MbCat$
LibTmp\LibTmpAA.obj    _MbClips
LibTmp\LibTmpAA.obj    _MbCurSlot
LibTmp\LibTmpAA.obj    _MbDebugBuffer
LibTmp\LibTmpAA.obj    _MbDebugLine
LibTmp\LibTmpAA.obj    _MbDebugNotPointer
LibTmp\LibTmpAA.obj    _MbDebugNull
LibTmp\LibTmpAA.obj    _MbDebugPtr
LibTmp\LibTmpAA.obj    _MbDebugR10
LibTmp\LibTmpAA.obj    _MbDebugR8
LibTmp\LibTmpAA.obj    _MbDebugStop
LibTmp\LibTmpAA.obj    _MbDebugTitle
LibTmp\LibTmpAA.obj    _MbDefNum
LibTmp\LibTmpAA.obj    _MbErrLine
LibTmp\LibTmpAA.obj    _MbError$
LibTmp\LibTmpAA.obj    _MbExeFolder$
LibTmp\LibTmpAA.obj    _MbFH
LibTmp\LibTmpAA.obj    _MbFlags
LibTmp\LibTmpAA.obj    _MbHeapTable
LibTmp\LibTmpAA.obj    _MbOfn
LibTmp\LibTmpAA.obj    _MbOfnX
LibTmp\LibTmpAA.obj    _MbPiBy180
LibTmp\LibTmpAA.obj    _MbProHeap
LibTmp\LibTmpAA.obj    _MbSlots
LibTmp\LibTmpAA.obj    _MbTIS
LibTmp\LibTmpAA.obj    _MbTmpQw
LibTmp\LibTmpAA.obj    _MbXs
LibTmp\LibTmpAA.obj    _MiscStrings
LibTmp\LibTmpAA.obj    _MousePos
LibTmp\LibTmpAA.obj    _PI
LibTmp\LibTmpAA.obj    _Spc1_txt
LibTmp\LibTmpAA.obj    _Spc2_txt
LibTmp\LibTmpAA.obj    _Spc3_txt
LibTmp\LibTmpAA.obj    _Spc4_txt
LibTmp\LibTmpAA.obj    _StringFillBuffer
LibTmp\LibTmpAA.obj    _Tab_txt
LibTmp\LibTmpAA.obj    _Tb$
LibTmp\LibTmpAA.obj    _ccnOld
LibTmp\LibTmpAA.obj    _f2sOlly
LibTmp\LibTmpAA.obj    _gcHeapA
LibTmp\LibTmpAA.obj    _gcHeapF
LibTmp\LibTmpAA.obj    _gvStart
LibTmp\LibTmpAA.obj    _hSetWin
LibTmp\LibTmpAA.obj    _txBOM
LibTmp\LibTmpAA.obj    _txEmpty
LibTmp\LibTmpAA.obj    _txQuest
LibTmp\LibTmpAA.obj    _txSpTbSpSp
LibTmp\LibTmpAA.obj    _wCrLf_txt
LibTmp\LibTmpAA.obj    _wLf_txt
LibTmp\LibTmpAA.obj    _wTab_txt
LibTmp\LibTmpAA.obj    _wfd
LibTmp\LibTmpAC.obj    _ArrSearchP@0
LibTmp\LibTmpAC.obj    _Browse4Folder@16
LibTmp\LibTmpAY.obj    _CanvasInfo
LibTmp\LibTmpAI.obj    _ClearLocalsP@0
LibTmp\LibTmpAA.obj    _Cr$
LibTmp\LibTmpAA.obj    _CrLf$
LibTmp\LibTmpAA.obj    _CrLf_txt
LibTmp\LibTmpAA.obj    _DebFile$
LibTmp\LibTmpAA.obj    _DllTable
LibTmp\LibTmpAF.obj    _DtFormat
LibTmp\LibTmpAA.obj    _Dw2BinBuffer
LibTmp\LibTmpAA.obj    _Dw2BinTable
LibTmp\LibTmpAA.obj    _EspGlob
LibTmp\LibTmpAG.obj    _ExtractP@24
LibTmp\LibTmpAA.obj    _FifHandle
LibTmp\LibTmpAA.obj    _FifRetBuf
LibTmp\LibTmpAC.obj    _FileReadP@4
LibTmp\LibTmpAF.obj    _FindInFile@20
LibTmp\LibTmpAK.obj    _Float2Asc@12
LibTmp\LibTmpAS.obj    _GdiSI
LibTmp\LibTmpAS.obj    _GdiStatus$
LibTmp\LibTmpAS.obj    _GetEncoderCLSID@4
LibTmp\LibTmpAB.obj    _GetNumID@0
LibTmp\LibTmpAB.obj    _GetStringID@0
LibTmp\LibTmpAF.obj    _GfDateTimeP@8
LibTmp\LibTmpAS.obj    _GuiNeedsPaint
LibTmp\LibTmpBB.obj    _GuiSMP@4
LibTmp\LibTmpAS.obj    _ImgPaintP@12
LibTmp\LibTmpBA.obj    _InsJb@12
LibTmp\LibTmpAG.obj    _InstrCi@16
LibTmp\LibTmpAB.obj    _IsRichP@0
LibTmp\LibTmpAB.obj    _JJ
LibTmp\LibTmpAB.obj    _LetEndPos
LibTmp\LibTmpAA.obj    _Lf$
LibTmp\LibTmpBA.obj    _LineCountP@0
LibTmp\LibTmpAB.obj    _LocateP@0
LibTmp\LibTmpAB.obj    _MbAR@0
LibTmp\LibTmpAB.obj    _MbAddToHeapTable@0
LibTmp\LibTmpAB.obj    _MbAllocP@0
LibTmp\LibTmpAB.obj    _MbArGetCTH
LibTmp\LibTmpAB.obj    _MbArGetErased
LibTmp\LibTmpAA.obj    _MbArrEmpty
LibTmp\LibTmpAV.obj    _MbArrSort@16
LibTmp\LibTmpAA.obj    _MbArrTable
LibTmp\LibTmpAB.obj    _MbArrayDim@8
LibTmp\LibTmpAB.obj    _MbArrayErase@0
LibTmp\LibTmpAB.obj    _MbArrayGet@8
LibTmp\LibTmpAY.obj    _MbArrayPlot@28
LibTmp\LibTmpAB.obj    _MbArraySwap@0
LibTmp\LibTmpAH.obj    _MbBinP@0
LibTmp\LibTmpAK.obj    _MbBufferFix@0
LibTmp\LibTmpAK.obj    _MbBufferGet@0
LibTmp\LibTmpAK.obj    _MbBufferInit@0
LibTmp\LibTmpAA.obj    _MbBufferStart
LibTmp\LibTmpAA.obj    _MbBytes2Write
LibTmp\LibTmpAA.obj    _MbCF
LibTmp\LibTmpAA.obj    _MbCat$
LibTmp\LibTmpAB.obj    _MbClipP@0
LibTmp\LibTmpAA.obj    _MbClips
LibTmp\LibTmpAC.obj    _MbClose@0
LibTmp\LibTmpAD.obj    _MbCol@0
LibTmp\LibTmpAD.obj    _MbColCust
LibTmp\LibTmpAE.obj    _MbCopy@12
LibTmp\LibTmpAE.obj    _MbCopyz@8
LibTmp\LibTmpAA.obj    _MbCurSlot
LibTmp\LibTmpAC.obj    _MbD2m
LibTmp\LibTmpAY.obj    _MbDBM@8
LibTmp\LibTmpAF.obj    _MbDTF@8
LibTmp\LibTmpAY.obj    _MbDbGetRgn@8
LibTmp\LibTmpAA.obj    _MbDebugBuffer
LibTmp\LibTmpAA.obj    _MbDebugLine
LibTmp\LibTmpAA.obj    _MbDebugNotPointer
LibTmp\LibTmpAA.obj    _MbDebugNull
LibTmp\LibTmpAA.obj    _MbDebugPtr
LibTmp\LibTmpAA.obj    _MbDebugR10
LibTmp\LibTmpAA.obj    _MbDebugR8
LibTmp\LibTmpAA.obj    _MbDebugStop
LibTmp\LibTmpAA.obj    _MbDebugTitle
LibTmp\LibTmpAA.obj    _MbDefNum
LibTmp\LibTmpAB.obj    _MbDimStruct@12
LibTmp\LibTmpAW.obj    _MbDlgP@16
LibTmp\LibTmpAB.obj    _MbErrAddLine
LibTmp\LibTmpAA.obj    _MbErrLine
LibTmp\LibTmpAB.obj    _MbErrTMS
LibTmp\LibTmpAA.obj    _MbError$
LibTmp\LibTmpAB.obj    _MbError0
LibTmp\LibTmpAB.obj    _MbError1
LibTmp\LibTmpAB.obj    _MbError10
LibTmp\LibTmpAB.obj    _MbError2
LibTmp\LibTmpAB.obj    _MbError3
LibTmp\LibTmpAB.obj    _MbError5
LibTmp\LibTmpAB.obj    _MbError6
LibTmp\LibTmpAB.obj    _MbErrorBuffer
LibTmp\LibTmpAA.obj    _MbExeFolder$
LibTmp\LibTmpAC.obj    _MbExistP@0
LibTmp\LibTmpAK.obj    _MbExp@0
LibTmp\LibTmpAA.obj    _MbFH
LibTmp\LibTmpAG.obj    _MbFileCmp@12
LibTmp\LibTmpBG.obj    _MbFindPro@0
LibTmp\LibTmpAA.obj    _MbFlags
LibTmp\LibTmpAR.obj    _MbFlipP@0
LibTmp\LibTmpAK.obj    _MbFloatCmp@0
LibTmp\LibTmpAD.obj    _MbFnt@8
LibTmp\LibTmpAK.obj    _MbFpuStatusP@0
LibTmp\LibTmpAB.obj    _MbFreeP@0
LibTmp\LibTmpAS.obj    _MbGdiInit@0
LibTmp\LibTmpAC.obj    _MbGetCL@0
LibTmp\LibTmpAF.obj    _MbGetFileCount
LibTmp\LibTmpAC.obj    _MbGetFileLen@4
LibTmp\LibTmpAB.obj    _MbGetKeyP@0
LibTmp\LibTmpBB.obj    _MbGetLG@0
LibTmp\LibTmpAY.obj    _MbGetMapIndex@0
LibTmp\LibTmpAK.obj    _MbGetSlotPointer@0
LibTmp\LibTmpAB.obj    _MbHeap16@0
LibTmp\LibTmpAA.obj    _MbHeapTable
LibTmp\LibTmpAH.obj    _MbHexP@8
LibTmp\LibTmpAC.obj    _MbInputP@0
LibTmp\LibTmpAB.obj    _MbInputStrP@8
LibTmp\LibTmpAB.obj    _MbInsNum@8
LibTmp\LibTmpAB.obj    _MbInsert@0
LibTmp\LibTmpAO.obj    _MbLMR@12
LibTmp\LibTmpAJ.obj    _MbLaMs
LibTmp\LibTmpAB.obj    _MbLenTable
LibTmp\LibTmpAK.obj    _MbLoadRich@0
LibTmp\LibTmpAQ.obj    _MbMD5@12
LibTmp\LibTmpAH.obj    _MbMulQQ@8
LibTmp\LibTmpAB.obj    _MbNewP
LibTmp\LibTmpAA.obj    _MbOfn
LibTmp\LibTmpAA.obj    _MbOfnX
LibTmp\LibTmpAC.obj    _MbOpenFile@20
LibTmp\LibTmpBG.obj    _MbPDat@0
LibTmp\LibTmpBE.obj    _MbPS
LibTmp\LibTmpAA.obj    _MbPiBy180
LibTmp\LibTmpBC.obj    _MbPoly3
LibTmp\LibTmpAB.obj    _MbPrint@0
LibTmp\LibTmpBE.obj    _MbPrintRtf@4
LibTmp\LibTmpAA.obj    _MbProHeap
LibTmp\LibTmpAT.obj    _MbQSortP@8
LibTmp\LibTmpAB.obj    _MbRegs32
LibTmp\LibTmpAB.obj    _MbReplPrep@16
LibTmp\LibTmpAC.obj    _MbResString@0
LibTmp\LibTmpAQ.obj    _MbRk64
LibTmp\LibTmpAB.obj    _MbRs@0
LibTmp\LibTmpAB.obj    _MbSAP@0
LibTmp\LibTmpAB.obj    _MbSCP@0
LibTmp\LibTmpBC.obj    _MbSinP@0
LibTmp\LibTmpAB.obj    _MbSleep@0
LibTmp\LibTmpAA.obj    _MbSlots
LibTmp\LibTmpAN.obj    _MbSound@0
LibTmp\LibTmpBD.obj    _MbSpriteP
LibTmp\LibTmpBD.obj    _MbSpriteTable
LibTmp\LibTmpAI.obj    _MbStackB@0
LibTmp\LibTmpAB.obj    _MbStdIn@0
LibTmp\LibTmpAB.obj    _MbStdOut@0
LibTmp\LibTmpAT.obj    _MbStrCmp@12
LibTmp\LibTmpAC.obj    _MbStrLen@0
LibTmp\LibTmpAC.obj    _MbStrLenW@0
LibTmp\LibTmpAB.obj    _MbStringErase@0
LibTmp\LibTmpAB.obj    _MbStructCopy@0
LibTmp\LibTmpAB.obj    _MbStructErase@4
LibTmp\LibTmpBB.obj    _MbTBar@16
LibTmp\LibTmpAA.obj    _MbTIS
LibTmp\LibTmpBF.obj    _MbTestRet@0
LibTmp\LibTmpAA.obj    _MbTmpQw
LibTmp\LibTmpAO.obj    _MbTrim@8
LibTmp\LibTmpAB.obj    _MbTxt2Dw@16
LibTmp\LibTmpAZ.obj    _MbUZ@8
LibTmp\LibTmpAO.obj    _MbUpperLowerP@8
LibTmp\LibTmpAL.obj    _MbUtf8@0
LibTmp\LibTmpBF.obj    _MbVI@12
LibTmp\LibTmpAK.obj    _MbVal@12
LibTmp\LibTmpBD.obj    _MbWarp@20
LibTmp\LibTmpAP.obj    _MbWinGh@0
LibTmp\LibTmpAD.obj    _MbWinStrP@8
LibTmp\LibTmpAX.obj    _MbXls@8
LibTmp\LibTmpAA.obj    _MbXs
LibTmp\LibTmpAO.obj    _Mb_SCB@0
LibTmp\LibTmpAU.obj    _MbwInputStrP@8
LibTmp\LibTmpAB.obj    _MbwRec@0
LibTmp\LibTmpAA.obj    _MiscStrings
LibTmp\LibTmpAN.obj    _MouseKeys@0
LibTmp\LibTmpAA.obj    _MousePos
LibTmp\LibTmpAL.obj    _MsgTableP@12
LibTmp\LibTmpAB.obj    _NewStrP@0
LibTmp\LibTmpAN.obj    _NoTagP@0
LibTmp\LibTmpAC.obj    _Open_for_input@12
LibTmp\LibTmpAC.obj    _Open_for_output@12
LibTmp\LibTmpAA.obj    _PI
LibTmp\LibTmpAN.obj    _PromptWM@0
LibTmp\LibTmpAT.obj    _QsMode
LibTmp\LibTmpAH.obj    _R10ToX@0
LibTmp\LibTmpAH.obj    _R16ToST@0
LibTmp\LibTmpBE.obj    _ReRgP@16
LibTmp\LibTmpAC.obj    _RecallP@16
LibTmp\LibTmpAQ.obj    _RegKeyP@16
LibTmp\LibTmpAK.obj    _RichEditUsed
LibTmp\LibTmpAJ.obj    _ShellWait@16
LibTmp\LibTmpAA.obj    _Spc1_txt
LibTmp\LibTmpAA.obj    _Spc2_txt
LibTmp\LibTmpAA.obj    _Spc3_txt
LibTmp\LibTmpAA.obj    _Spc4_txt
LibTmp\LibTmpBD.obj    _SprBuffer
LibTmp\LibTmpAC.obj    _StoreHead$
LibTmp\LibTmpAC.obj    _StoreP@12
LibTmp\LibTmpAB.obj    _StreamFromPtr@16
LibTmp\LibTmpAB.obj    _StreamFromPtrP@16
LibTmp\LibTmpAM.obj    _StringFill@0
LibTmp\LibTmpAA.obj    _StringFillBuffer
LibTmp\LibTmpAA.obj    _Tab_txt
LibTmp\LibTmpAA.obj    _Tb$
LibTmp\LibTmpAC.obj    _TclCatch1
LibTmp\LibTmpAC.obj    _TclTry1
LibTmp\LibTmpAB.obj    _TestRetVal@0
LibTmp\LibTmpAC.obj    _TouchP@8
LibTmp\LibTmpAJ.obj    _WriteData@8
LibTmp\LibTmpAY.obj    _apStruct
LibTmp\LibTmpBB.obj    _cbRN@16
LibTmp\LibTmpAA.obj    _ccnOld
LibTmp\LibTmpAA.obj    _f2sOlly
LibTmp\LibTmpAA.obj    _gcHeapA
LibTmp\LibTmpAA.obj    _gcHeapF
LibTmp\LibTmpAS.obj    _gdiSmoothing
LibTmp\LibTmpAA.obj    _gvStart
LibTmp\LibTmpAS.obj    _hCanvas4Image
LibTmp\LibTmpAA.obj    _hSetWin
LibTmp\LibTmpAG.obj    _isCurPos
LibTmp\LibTmpAC.obj    _isUtf8P@0
LibTmp\LibTmpAJ.obj    _lsp
LibTmp\LibTmpAC.obj    _ofSQ@0
LibTmp\LibTmpAK.obj    _pcTable
LibTmp\LibTmpAH.obj    _qmFuncs
LibTmp\LibTmpAH.obj    _qmP@0
LibTmp\LibTmpBB.obj    _tbs0
LibTmp\LibTmpAA.obj    _txBOM
LibTmp\LibTmpAA.obj    _txEmpty
LibTmp\LibTmpAB.obj    _txFatal
LibTmp\LibTmpAC.obj    _txFrl
LibTmp\LibTmpAA.obj    _txQuest
LibTmp\LibTmpAC.obj    _txRNF
LibTmp\LibTmpAA.obj    _txSpTbSpSp
LibTmp\LibTmpBF.obj    _txViStrings
LibTmp\LibTmpAA.obj    _wCrLf_txt
LibTmp\LibTmpAL.obj    _wDataP@0
LibTmp\LibTmpAA.obj    _wLf_txt
LibTmp\LibTmpAA.obj    _wTab_txt
LibTmp\LibTmpAN.obj    _wcxP$
LibTmp\LibTmpAA.obj    _wfd
LibTmp\LibTmpAX.obj    _xlsServer$
LibTmp\LibTmpAZ.obj    _xzmb
Title: Re: How complicated is the code for Microsoft Windows?
Post by: hutch-- on January 26, 2020, 10:03:48 AM
I remember long long ago that people slavishly aped Petzold's code format without ever understanding it. Petzold wrote hybrid code when 16 and 32 bit API code were both being used and his code could be switched between the two.

As far as COM, it was deliberately obscure as it shut off alternative OS versions from using it but it was always a complicated mess with unnecessary overhead that few would manually code.
Title: Re: How complicated is the code for Microsoft Windows?
Post by: jj2007 on February 01, 2020, 12:02:37 PM
https://www.quora.com/As-a-software-developer-what-is-the-most-inappropriate-variable-name-youve-ever-seen
Quote
When I worked for Microsoft Office, I reviewed a code change to remove offensive words from the source code, in preparation for sharing it with partners. There were no truly offensive variable names. However…

There was a developer tool that helped developers add asserts (in-line tests). Each assert was labeled with an automatically generated four letter tag. You can see how this would go wrong.

Among others, we removed asserts labeled 'nazi’, 'c*nt', and for good measure, 'bich'.
Quote
When the consultant came back from vacation the company placed an emergency call to him to come look at the code. They asked him what LVBRIP was used for and he said, “Oh, that’s the pointer to the current location in the print buffer.” They asked why it was called LVBRIP, and he, being a Music History major said, “1827 is the year Ludwig van Beethoven died.”

They fired him on the spot.
Quote
there are far over 9k calls to goto in the code. That’s not an accurate count though because there are quite a few helper functions that also call goto and those are used everywhere as well. If I were to guess you could probably calculate the calls to goto more in the range of 30k - 50k.

This is all C code that is written by a lady who was an assembly programmer and never changed her ways for 30 or more years
Quote
Not only was it a monster of spaghetti, but every single variable was named after a Marvel comic book character.
Title: Re: How complicated is the code for Microsoft Windows?
Post by: HSE on February 02, 2020, 12:47:01 AM
 :biggrin:
Title: Re: How complicated is the code for Microsoft Windows?
Post by: hutch-- on February 02, 2020, 01:00:15 AM
 :biggrin:

> Not only was it a monster of spaghetti

For most who have only heard of spaghetti code, its a lot harder to write than many would thinks, absolute line numbers as targets for the seriously maligned GOTO. As compiler can count lines without the programmer needing them to do so, the loss of line numbers was no big deal. Most of the whining about GOTO and labels comes from people who cannot read or design complex logic.
Title: Re: How complicated is the code for Microsoft Windows?
Post by: jj2007 on February 02, 2020, 01:18:46 AM
Right. The only GOTO that I used persistently (after the first few weeks of learning) had only one purpose: Jump over an area (Print "123...") where I loaded 68000 assembly code... for GfaBasic users, GOTO was dead from 1987 onwards, over 30 years ago. Which doesn't stop the C/C++/C# gang to blame BASIC for "spaghetti monsters", of course. I get the creeps when I am forced to look at C++ sources :mrgreen:

The proggie is still working btw, using the Steem emulator. It's a blazing fast text processor, 15k lines of GfaBasic source plus 3k lines of 68k Assembly. With integrated graphics and plot facility. I've written even the printer driver, and managed to write, print and publish a book with a renommated scientific publisher. Shortly afterwards my employer forced me to switch to Windows :sad:
Title: Re: How complicated is the code for Microsoft Windows?
Post by: Siekmanski on February 02, 2020, 02:04:29 AM
 :biggrin:

> I get the creeps when I am forced to look at C++ sources :mrgreen:

I share the same feeling, remember the DirectShow Video Grabber C++ conversion we played with?
Title: Re: How complicated is the code for Microsoft Windows?
Post by: felipe on February 02, 2020, 02:11:35 AM
written by a lady who was an assembly programmer and never changed her ways for 30 or more years

Can't see anything wrong here... :biggrin: A lady who was an assembly programmer...was a forum member too???  :tongue:
Title: Re: How complicated is the code for Microsoft Windows?
Post by: caballero on February 02, 2020, 03:43:27 AM
Spaghetti code is awful. Refusing at all to use gotos is stupid.
Title: Re: How complicated is the code for Microsoft Windows?
Post by: AW on February 02, 2020, 06:37:08 AM
gotophobia is a clear sickness.
Donald Knuth wrote an article "Structured Programming with GOTO Statements" - but most considerations apply mainly to High Level Languages. Assembly has no better alternative than using pure conditional or unconditional "GOTO", this conclusion reached the developers of MASM64 bit when decided to eliminate the WHILE and REPEAT pseudo-instructions.  Assembly is close to bare metal, who does not like bare metal will do better with an HLL.
Title: Re: How complicated is the code for Microsoft Windows?
Post by: jj2007 on February 02, 2020, 08:02:25 AM
Spaghetti code is awful. Refusing at all to use gotos is stupid.

Agreed. But in GfaBasic at least, I never ever saw a need for GOTOs. In Assembly, I use jmp very rarely, but conditional jumps are frequent. If possible, though, I use .Repeat ... .Until, because it's fast and clear. And Switch in a WndProc is a must.
Title: Re: How complicated is the code for Microsoft Windows?
Post by: daydreamer on February 02, 2020, 08:06:50 AM
gotophobia is a clear sickness.
Donald Knuth wrote an article "Structured Programming with GOTO Statements" - but most considerations apply mainly to High Level Languages. Assembly has no better alternative than using pure conditional or unconditional "GOTO", this conclusion reached the developers of MASM64 bit when decided to eliminate the WHILE and REPEAT pseudo-instructions.  Assembly is close to bare metal, who does not like bare metal will do better with an HLL.
while and repeat are macros probably can be remade with macro caps if wanted ,not my favourite loop is forloop
still if you love to use switch/case much in C,the compiled code ends up with lots of jumps
Title: Re: How complicated is the code for Microsoft Windows?
Post by: morgot on February 07, 2020, 02:48:27 AM
COM is terrible from ASM and from C/C++.
It is easy from Delphi and also from the .Net languages.
All high-level languages are simple because they hide abstraction. As an example, wininet is simpler than sockets, and the Indy components (delphi / C ++ collector) are even simpler. But a normal programmer must understand how everything works inside. Because all this is based on low-level languages. In case of an error in Masm or C, I will take a debugger and look.

But in Linux all things are simpler, that in Windows. This is fact.
p.s. in some interview i read , that microsoft programmers used LSD, when creating Windows.. It look likes true.
Title: Re: How complicated is the code for Microsoft Windows?
Post by: AW on February 07, 2020, 10:29:52 PM
But in Linux all things are simpler, that in Windows. This is fact.

It is never a waste of time to create another Windows versus Linux war.  :biggrin:
Title: Re: How complicated is the code for Microsoft Windows?
Post by: nidud on February 08, 2020, 12:15:13 AM
COM is terrible from ASM and from C/C++.

I will argue there's a big difference between C and C++ with regards to COM but (at least now) the assembler interface is actually simpler than C++.

include windows.inc
include shlobj.inc

    .code

wmain proc

  local link:ptr IShellLinkW
  local file:ptr IPersistFile

    CoInitialize(NULL)
    .ifd CoCreateInstance(&CLSID_ShellLink, NULL,
            CLSCTX_INPROC_SERVER, &IID_IShellLink, &link) == S_OK

        link.QueryInterface(&IID_IPersistFile, &file)
        link.SetPath("N:\\dir\\some file that doesn't exist.txt")
        file.Save("test.lnk", TRUE)
    .endif
    xor eax,eax
    ret

wmain endp

    end

Quote
We should not try to understand in detail how it works, we will never get it...
Rule: Don't try to understand in detail, you will never get it, just learn how to obtain results.

 :biggrin:

Somewhat true as it is more complicated to create than use but it is after all one of the simplest object constructs there is. And as for the hidden abstractions it should be in range of being possible to understand.

wmain   PROC
        push    rbp                                     
        mov     rbp, rsp                               
        sub     rsp, 64                                 
        xor     ecx, ecx                               
        call    CoInitialize                           
        lea     rax, [rbp-8H]                           
        mov     qword ptr [rsp+20H], rax               
        lea     r9, [IID_IShellLinkA]                   
        mov     r8d, 1                                 
        xor     edx, edx                               
        lea     rcx, [CLSID_ShellLink]                 
        call    CoCreateInstance                       
        test    eax, eax                               
        jnz     ?_001                                   
        lea     r8, [rbp-10H]                           
        lea     rdx, [IID_IPersistFile]                 
        mov     rcx, qword ptr [rbp-8H]                 
        mov     rax, qword ptr [rcx]                   
        call    qword ptr [rax]                         
        lea     rdx, [DS0000]                           
        mov     rcx, qword ptr [rbp-8H]                 
        mov     rax, qword ptr [rcx]                   
        call    qword ptr [rax+0A0H]                   
        mov     r8d, 1                                 
        lea     rdx, [DS0001]                           
        mov     rcx, qword ptr [rbp-10H]               
        mov     rax, qword ptr [rcx]                   
        call    qword ptr [rax+30H]                     
?_001:  xor     eax, eax                               
        leave                                           
        ret                                             
wmain   ENDP
Title: Re: How complicated is the code for Microsoft Windows?
Post by: jj2007 on February 08, 2020, 12:46:41 AM
I prefer BASIC :tongue:

include \masm32\MasmBasic\MasmBasic.inc
.code
CLSID_IExplorer         GuidFromString("0002DF01-0000-0000-C000-000000000046")  ; either use quoted text syntax or...
IID_IWebBrowser2        GuidFromString({D30C1661-CDAF-11D0-8A3E-00C04FC9E26E})  ; ... paste copied registry key name
MyBrowser proc uses edi url
LOCAL vEmpty:VARIANT, hWin, WebInterface
  ClearLocals
  lea edi, WebInterface
  pInterface equ dword ptr [edi]
  .if rv(CoCreateInstance, addr CLSID_IExplorer, NULL, CLSCTX_LOCAL_SERVER, addr IID_IWebBrowser2, edi)==S_OK
       CoInvoke pInterface, IWebBrowserVtbl.put_StatusBar, VARIANT_FALSE       ; OK, now configure the browser
       CoInvoke pInterface, IWebBrowserVtbl.put_MenuBar, VARIANT_FALSE         ; false = no menu
       CoInvoke pInterface, IWebBrowserVtbl.put_Visible, VARIANT_TRUE
       CoInvoke pInterface, IWebBrowserVtbl.get_HWND, addr hWin
       lea edx, vEmpty         ; Navigate needs pointers to four empty VARIANTS
       CoInvoke pInterface, IWebBrowserVtbl.Navigate, Ole$(url), edx, edx, edx, edx
  .endif
  ret
MyBrowser endp
  Init                          ; ## COM demo: open Internet Explorer ##
  .if rv(OleInitialize, NULL)==S_OK
        invoke MyBrowser, Chr$("http://masm32.com/board/index.php?action=unread")
        invoke OleUninitialize
  .endif
EndOfCode
Title: Re: How complicated is the code for Microsoft Windows?
Post by: AW on February 08, 2020, 01:00:08 AM
@nidud,
I have not seen many times (sorry, actually I have never seen  :sad:) such trivial things as ActiveX controls, COM servers or even accessing the WMI functionality, from code produced in ASM. I know some developers have huge libraries supporting their ASM or pseudo-ASM tools (also called pure-MASM), but even with such arsenal nothing comes out.  :sad:
Title: Re: How complicated is the code for Microsoft Windows?
Post by: nidud on February 08, 2020, 02:36:03 AM
So lets make a simple one then and see how it works. This from a sample adding syntax highlighting to a RichEdit control. We may then start with the user side first. The user needs the COM structure and GUID to load the object. The class is called IConfig and basically just read and write a .INI file.

.comdef IConfig : public IUnknown

    read            proc :string_t
    write           proc :string_t
    find            proc :string_t
    create          proc :string_t, :vararg
    getvalue        proc :string_t, :string_t
    delete          proc :string_t

    .ends

The test case loads the DLL and creates a simple config file.
Code: [Select]
include objbase.inc
include tchar.inc
include IConfig.inc
include locals.inc

    .data
    IID_IClassFactory IID _IID_IClassFactory
    IID_IConfig       IID _IID_IConfig
    CLSID_IConfig     IID _CLSID_IConfig

    .code

WinMain proc hInstance:HINSTANCE, hPrevInstance:HINSTANCE, lpCmdLine:LPTSTR, nShowCmd:SINT

    local config:ptr IConfig
    local class:ptr IClassFactory
    local hr:HRESULT

    .ifd !CoInitialize(0)

        .ifd CoGetClassObject(&CLSID_IConfig, CLSCTX_INPROC_SERVER, 0, &IID_IClassFactory, &class)

            MessageBox(0, "Can't get IClassFactory", "CoGetClassObject error", MB_OK or MB_ICONEXCLAMATION)
        .else

            .ifd class.CreateInstance(0, &IID_IConfig, &config)

                MessageBox(0, "Can't create IConfig object", "CreateInstance error",
                        MB_OK or MB_ICONEXCLAMATION)

            .else

                assume rcx:ptr IConfig
                config.create( "Version" )
                [rcx].create ( "Base=%d.%d", 1, 0 )
                config.create( "Product" )
                [rcx].create ( "Source=IConfig COM component" )
                config.create( "URL" )
                [rcx].create ( "UpdateURL=https://github.com/nidud/asmc/tree/master/source/test/comdll" )
                config.find  ( "Version" )
                [rcx].create ( "Package=%d.%d", 1, 0 )
                config.write ( "test.ini" )
                config.Release()
            .endif
            class.Release()
        .endif
        CoUninitialize()
    .else
        MessageBox(0, "Can't initialize COM", "CoInitialize error", MB_OK or MB_ICONEXCLAMATION)
    .endif
    xor eax,eax
    ret

WinMain endp

    end _tstart

So to the hard part.

; locals.inc
; set the local path and use guidgen.exe to create the two GUIDs below.
; then remove this..
.err <GUIDs not created -- see locals.inc>

dll_path    equ <"D:\\Asmc\\source\\test\\comdll\\IConfig.dll">
dll_clsid   equ <"{09BE7B0C-2275-474D-9405-24AAB891614F}">

DEFINE_GUIDS(IID_IConfig,   "7BF9D277-13A2-4815-B3E9-CDE77C5906C3")
DEFINE_GUIDS(CLSID_IConfig, "09BE7B0C-2275-474D-9405-24AAB891614F")

Install
Code: [Select]
include windows.inc
include stdio.inc
include winreg.inc
include locals.inc

    .code

wmain proc

  local hKey0:HKEY, hKey1:HKEY, hKey2:HKEY, hKey3:HKEY
  local Disposition:int_t, retval:int_t

    mov retval,1

    .if !RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Classes", 0, KEY_WRITE, &hKey0)

        .if !RegOpenKeyEx(hKey0, "CLSID", 0, KEY_ALL_ACCESS, &hKey1)

            .if !RegCreateKeyEx(hKey1, dll_clsid, 0, 0, REG_OPTION_NON_VOLATILE,
                    KEY_WRITE, 0, &hKey2, &Disposition)

                RegSetValueEx(hKey2, 0, 0, REG_SZ, "IConfig COM component", sizeof(DS0003))

                .if !RegCreateKeyEx(hKey2, "InprocServer32", 0, 0, REG_OPTION_NON_VOLATILE,
                        KEY_WRITE, 0, &hKey3, &Disposition)

                    .if !RegSetValueEx(hKey3, 0, 0, REG_SZ, dll_path, sizeof(DS0005))

                        .if !RegSetValueEx(hKey3, "ThreadingModel", 0, REG_SZ,
                                "both", sizeof(DS0007))

                            mov retval,0
                            wprintf("Successfully registered IConfig.dll as a COM component.\n")
                        .endif
                    .endif
                    RegCloseKey(hKey3)
                .endif
                RegCloseKey(hKey2)
            .endif
            RegCloseKey(hKey1)
        .endif
        RegCloseKey(hKey0)
    .endif

    .if ( retval )

        wprintf("Failed to registered IConfig.dll as a COM component.\n")

        .ifd !RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Classes", 0, KEY_WRITE, &hKey0)

            .ifd !RegOpenKeyEx(hKey0, "CLSID", 0, KEY_ALL_ACCESS, &hKey1)

                .ifd !RegCreateKeyEx(hKey1, dll_clsid, 0, 0, REG_OPTION_NON_VOLATILE,
                        KEY_WRITE, 0, &hKey2, &Disposition)

                    RegDeleteKey(hKey2, "InprocServer32")
                    RegCloseKey(hKey2)
                    RegDeleteKey(hKey1, dll_clsid)
                .endif
                RegCloseKey(hKey1)
            .endif
            RegCloseKey(hKey0)
        .endif
    .endif

    exit(retval)

wmain endp

    end wmain

UnInstall
Code: [Select]
include windows.inc
include stdio.inc
include winreg.inc
include locals.inc

    .code

wmain proc

  local hKey0:HKEY, hKey1:HKEY, hKey2:HKEY
  local Disposition:int_t, retval:int_t

    mov retval,1
    .ifd !RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Classes", 0, KEY_WRITE, &hKey0)

        .ifd !RegOpenKeyEx(hKey0, "CLSID", 0, KEY_ALL_ACCESS, &hKey1)

            .ifd !RegCreateKeyEx(hKey1, dll_clsid, 0, 0, REG_OPTION_NON_VOLATILE,
                        KEY_WRITE, 0, &hKey2, &Disposition)

                .ifd !RegDeleteKey(hKey2, "InprocServer32")

                    RegCloseKey(hKey2)
                    .ifd !RegDeleteKey(hKey1, dll_clsid)

                        mov retval,0
                        wprintf("Successfully removed IConfig.dll as a COM component.\n")
                    .endif
                .endif
            .endif
            RegCloseKey(hKey1)
        .endif
        RegCloseKey(hKey0)
    .endif

    .if retval

        wprintf("Failed to remove IConfig.dll as a COM component.\n")
    .endif

    exit(retval)
    ret

wmain endp

    end wmain

The DLL file
Code: [Select]
include objbase.inc
include intrin.inc
include stdio.inc
include IConfig.inc
include locals.inc

.comdef CIClassFactory

    ref_count       dd ?

    QueryInterface  proc :REFIID, :ptr
    AddRef          proc
    Release         proc

    CreateInstance  proc :ptr, :REFIID, :ptr
    LockServer      proc :BOOL

    .ends


_I_BASE             equ 0x01
_I_SECTION          equ 0x02
_I_ENTRY            equ 0x04
_I_COMMENT          equ 0x08


.comdef CIConfig

    count           uint_t ?
    flags           uint_t ?
    name            string_t ?
    union
      value         string_t ?
      list          ptr_t ?
    ends
    next            ptr_t ?
    Compare         proc local :string_t, :string_t

    QueryInterface  proc :REFIID, :ptr
    AddRef          proc
    Release         proc

    read            proc :string_t
    write           proc :string_t
    find            proc :string_t
    create          proc :string_t, :vararg
    getvalue        proc :string_t, :string_t
    delete          proc :string_t
    new             proc
    unlink          proc :ptr_t

    .ends


    .data

    IID_IUnknown    IID _IID_IUnknown
    IID_IConfig     IID _IID_IConfig
    CLSID_IConfig   IID _CLSID_IConfig
    IID_IClassFactory IID _IID_IClassFactory

    ClassFactoryVtbl CIClassFactoryVtbl { \
        CIClassFactory_QueryInterface,
        CIClassFactory_AddRef,
        CIClassFactory_Release,
        CIClassFactory_CreateInstance,
        CIClassFactory_LockServer }

    ConfigVtbl CIConfigVtbl { \
        CIConfig_QueryInterface,
        CIConfig_AddRef,
        CIConfig_Release,
        CIConfig_read,
        CIConfig_write,
        CIConfig_find,
        CIConfig_create,
        CIConfig_getvalue,
        CIConfig_delete,
        CIConfig_new,
        CIConfig_unlink }

    Config CIConfig { ConfigVtbl, 0, }
    ClassFactory CIClassFactory { ClassFactoryVtbl, 0 }
    OutstandingObjects int_t 0
    LockCount int_t 0

    .code

    assume rcx:ptr CIConfig

CIConfig::QueryInterface proc riid:LPIID, ppv:ptr ptr

    mov rax,[rdx]
    mov rdx,[rdx+8]
    .if rax == qword ptr IID_IUnknown
        cmp rdx,qword ptr IID_IUnknown[8]
    .endif
    .ifnz
        .if rax == qword ptr IID_IConfig
            cmp rdx,qword ptr IID_IConfig[8]
        .endif
    .endif
    .ifz
        mov [r8],rcx
        [rcx].AddRef()
        mov eax,NOERROR
    .else
        xor eax,eax
        mov [r8],rax
        mov eax,E_NOINTERFACE
    .endif
    ret

CIConfig::QueryInterface endp


CIConfig::AddRef proc

    inc [rcx].count
    mov eax,[rcx].count
    ret

CIConfig::AddRef endp


    assume rbx:ptr CIConfig

CIConfig::Release proc uses rbx

    dec [rcx].count
    .ifz

        mov rbx,rcx
        _InterlockedDecrement(&OutstandingObjects)

        .while rbx
            free([rbx].name)
            .if [rbx].flags & _I_SECTION
                mov rcx,[rbx].list
                .if rcx
                    [rcx].Release()
                .endif
            .endif
            mov rcx,rbx
            mov rbx,[rbx].next
            free(rcx)
        .endw

        xor eax,eax
    .else
        mov eax,[rcx].count
    .endif
    ret

CIConfig::Release endp


TruncateString proc private string:LPSTR

    .repeat

        mov al,[rcx]
        inc rcx

        .continue(0) .if al == ' '
        .continue(0) .if al == 9
        .continue(0) .if al == 10
        .continue(0) .if al == 13
    .until 1
    dec rcx

    mov rdx,rcx
    xor eax,eax
    .while [rcx] != al

        inc rcx
    .endw

    .repeat

        .break .if rcx <= rdx

        dec rcx
        mov al,[rcx]
        mov [rcx],ah

        .continue(0) .if al == ' '
        .continue(0) .if al == 9
        .continue(0) .if al == 10
        .continue(0) .if al == 13

        mov [rcx],al
        inc rcx

    .until 1

    sub rcx,rdx
    mov rax,rcx
    ret

TruncateString endp


CIConfig::read proc uses rsi rdi rbx r12 file:string_t

  local fp:LPFILE, buffer[256]:sbyte

    mov r12,rcx
    mov rbx,rcx
    mov rcx,rdx
    .if fopen(rcx, "rt")

        .for ( rdi = rax, rsi = &buffer : fgets(rsi, 256, rdi) : )

            .continue .ifd !TruncateString(rsi)

            .if byte ptr [rdx] == '['

                .if strchr(rsi, ']')

                    mov byte ptr [rax],0
                    .break .if ![rbx].create(&[rsi+1])
                    mov rbx,rax
                .endif
            .else
                [rbx].create(rdx)
            .endif
        .endf
        fclose(rdi)
        mov rax,r12
    .endif
    ret

CIConfig::read endp


CIConfig::write proc uses rsi rdi rbx file:string_t

    mov rbx,rcx
    mov rcx,rdx
    .if fopen(rcx, "wt")

        .for ( rdi = rax : rbx : rbx = [rbx].next )

            .if [rbx].flags & _I_SECTION

                fprintf(rdi, "\n[%s]\n", [rbx].name)
            .endif

            .for ( rsi=[rbx].list : rsi : rsi=[rsi].CIConfig.next )

                mov r8,[rsi].CIConfig.name
                mov eax,[rsi].CIConfig.flags
                .if eax & _I_ENTRY

                    fprintf(rdi, "%s=%s\n", r8, [rsi].CIConfig.value)
                .elseif eax & _I_COMMENT
                    fprintf(rdi, "%s\n", r8)
                .else
                    fprintf(rdi, ";%s\n", r8)
                .endif
            .endf
        .endf
        fclose(rdi)
        mov eax,1
    .endif
    ret
CIConfig::write endp


CIConfig::find proc uses rsi rdi rbx string:string_t

    xor edi,edi
    mov rsi,rdx
    xor eax,eax

    .while rcx

        .if ( [rcx].flags & ( _I_SECTION or _I_ENTRY ) )

            mov rbx,rcx
            .if !( [rbx].Compare([rbx].name, rsi) )

                mov rdx,rdi
                mov rcx,rbx
                mov rax,rbx
                .break
            .endif
            xor eax,eax
            mov rcx,rbx
        .endif
        mov rdi,rcx
        mov rcx,[rcx].next
    .endw
    ret

CIConfig::find endp


CIConfig::getvalue proc uses rsi rdi rbx Section:string_t, Entry:string_t

    mov rbx,rcx
    mov rsi,rdx
    mov rdi,r8

    .if [rbx].find(rdx)

        mov rax,[rcx].list
        .if rax

            [rax].CIConfig.find(rdi)
        .endif
    .endif
    ret

CIConfig::getvalue endp


CIConfig::create proc uses rsi rdi rbx r12 format:string_t, argptr:vararg

 local string[256]:sbyte

    mov rbx,rcx
    lea rdi,string

    .repeat

        .break .ifd !vsprintf(rdi, rdx, &argptr)
        .break .ifd !TruncateString(rdi)

        xor esi,esi
        mov rdi,rdx

        .if byte ptr [rdx] != ';'

            mov al,'='
            repnz scasb
            .ifz
                mov rsi,rdi
                mov byte ptr [rdi-1],0
                mov rdi,rdx
                TruncateString(rsi)
                TruncateString(rdi)
                mov rdx,rdi
            .endif
            mov rdi,rdx
        .endif

        .break .if [rbx].find(rdx)
        .break .if ![rbx].new()

        mov ecx,_I_SECTION
        .if esi
            mov byte ptr [rsi-1],'='
            mov ecx,_I_ENTRY
        .elseif byte ptr [rdi] == ';'
            mov ecx,_I_COMMENT
        .endif
        mov [rax].CIConfig.flags,ecx

        mov r12,rdi
        mov rdi,rax

        .break .if !malloc( &[ strlen( r12 ) + 1 ] )
        mov [rdi].CIConfig.name,strcpy( rax, r12 )

        mov rax,[rbx].next
        .if esi && [rbx].flags & _I_SECTION

            mov rax,[rbx].list
            .if !rax

                mov [rbx].list,rdi
                xor rbx,rbx
            .endif
        .endif

        .while rax

            mov rbx,rax
            mov rax,[rbx].next
        .endw

        .if rbx

            mov [rbx].next,rdi
        .endif

        mov rbx,rdi
        .if esi

            .if strchr([rbx].name, '=')

                mov byte ptr [rax],0
                inc rax
                mov [rbx].value,rax
            .endif
        .endif

        mov rax,rdi
    .until 1
    mov rcx,rax
    ret

CIConfig::create endp


CIConfig::new proc

    .return .if !malloc(CIConfig)

    mov rcx,rax
    mov [rcx].count,1
    lea rax,ConfigVtbl
    mov [rcx].lpVtbl,rax
    xor eax,eax
    mov [rcx].next,rax
    mov [rcx].name,rax
    mov [rcx].list,rax
    mov [rcx].flags,eax
    lea rax,strcmp
    mov [rcx].Compare,rax
    mov rax,rcx
    ret

CIConfig::new endp


CIConfig::delete proc SectionName:string_t

    .if [rcx].find(rdx)

        .if rdx

            [rax].CIConfig.unlink(rdx)
        .endif
    .endif
    ret

CIConfig::delete endp


CIConfig::unlink proc Parent:ptr

    mov rax,[rcx].next
    mov [rdx].CIConfig.next,rax
    xor eax,eax
    mov [rcx].next,rax
    [rcx].Release()
    ret

CIConfig::unlink endp


    assume rbx:nothing
    assume rcx:ptr CIClassFactory

CIClassFactory::QueryInterface proc riid:LPIID, ppv:ptr ptr

    mov rax,[rdx]
    mov rdx,[rdx+8]
    .if rax == qword ptr IID_IUnknown
        cmp rdx,qword ptr IID_IUnknown[8]
    .endif
    .ifnz
        .if rax == qword ptr IID_IClassFactory
            cmp rdx,qword ptr IID_IClassFactory[8]
        .endif
    .endif
    .ifz

        mov [r8],rcx
        [rcx].AddRef()
        mov eax,NOERROR

    .else

        xor eax,eax
        mov [r8],rax
        mov eax,E_NOINTERFACE
    .endif
    ret

CIClassFactory::QueryInterface endp


CIClassFactory::AddRef proc

    _InterlockedIncrement(&OutstandingObjects)
    ret

CIClassFactory::AddRef endp


CIClassFactory::Release proc

    _InterlockedDecrement(&OutstandingObjects)
    ret

CIClassFactory::Release endp


CIClassFactory::CreateInstance proc uses rdi rdi Unknown:ptr IUnknown, riid:REFIID, ppv:ptr

    xor eax,eax
    mov [r9],rax

    .if rdx

        mov eax,CLASS_E_NOAGGREGATION
    .else

        .if !malloc(sizeof(CIConfig))

            mov eax,E_OUTOFMEMORY
        .else

            assume rsi:ptr CIConfig
            mov rsi,rax
            lea rax,ConfigVtbl
            mov [rsi].lpVtbl,rax
            mov [rsi].count,1
            xor eax,eax
            mov [rsi].next,rax
            mov [rsi].name,rax
            mov [rsi].list,rax
            mov [rsi].flags,eax
            lea rax,strcmp
            mov [rsi].Compare,rax
            mov edi,[rsi].QueryInterface(riid, ppv)
            [rsi].Release()
            .if !edi

                _InterlockedIncrement(&OutstandingObjects)
            .endif
            assume rsi:nothing
            mov eax,edi
        .endif
    .endif
    ret

CIClassFactory::CreateInstance endp


CIClassFactory::LockServer proc flock:BOOL

    .if edx
        _InterlockedIncrement(&LockCount)
    .else
        _InterlockedDecrement(&LockCount)
    .endif

    mov eax,NOERROR
    ret

CIClassFactory::LockServer endp


    option win64:rsp nosave noauto

DllGetClassObject proc export frame rclsid:REFCLSID, riid:REFIID, ppv:ptr ptr

    mov rax,[rcx]
    mov rcx,[rcx+8]
    .if rax == qword ptr CLSID_IConfig
        cmp rcx,qword ptr CLSID_IConfig[8]
    .endif
    .ifz
        CIClassFactory::QueryInterface(&ClassFactory, rdx, r8)
    .else
        xor eax,eax
        mov [r8],rax
        mov eax,CLASS_E_CLASSNOTAVAILABLE
    .endif
    ret

DllGetClassObject endp


DllCanUnloadNow proc export

    mov eax,OutstandingObjects
    or  eax,LockCount
    .if eax
        mov eax,S_FALSE
    .else
        mov eax,S_OK
    .endif
    ret

DllCanUnloadNow endp


DllMain proc frame hinstDLL:HINSTANCE, fdwReason:DWORD, lpvReserved:LPVOID

    .if edx == DLL_PROCESS_ATTACH

        DisableThreadLibraryCalls(rcx)
    .endif
    mov eax,TRUE
    ret

DllMain endp

    end DllMain

makefile

test.exe:
    asmc64 -nologo -pe -gui $*.asm
    asmc64 -nologo -pe -ws install.asm
    asmc64 -nologo -pe -ws uninstall.asm
    asmc64 -nologo -D__GUID__ IConfig.asm
    linkw option quiet system dll_64 file IConfig.obj
    install.exe
    $@
    pause

This should give the output:
Successfully registered IConfig.dll as a COM component.
Then uninstall:
Successfully removed IConfig.dll as a COM component.
Again:
Failed to remove IConfig.dll as a COM component.

There should be a test.ini file created on success.
Title: Re: How complicated is the code for Microsoft Windows?
Post by: AW on February 08, 2020, 03:43:30 AM
It looks like a complete example, but I suspect it will not entice the Linux crowd to move to Windows :rolleyes:, in particular, with the argument that it is easy to do COM from ASM.

BTW, you can register the COM server in HKEY_CURRENT_USER, so there is no need to launch as administrator.
Title: Re: How complicated is the code for Microsoft Windows?
Post by: caballero on February 08, 2020, 04:12:43 AM
Interesting  :thumbsup:
Title: Re: How complicated is the code for Microsoft Windows?
Post by: Vortex on February 08, 2020, 04:41:05 AM
Hi morgot,

Quote
But in Linux all things are simpler, that in Windows. This is fact.

It depends. While I always tell that Linux is very good as a server operating system, some configuration files can be very complicated.
Title: Re: How complicated is the code for Microsoft Windows?
Post by: TimoVJL on February 08, 2020, 07:23:07 PM
Sometimes it's possible to use COM without register.

https://blogs.msdn.microsoft.com/junfeng/2006/04/20/com-activation-registration-free-com-activation-com-net-interop-registration-free-com-net-interop/

https://docs.microsoft.com/en-us/windows/win32/sbscs/creating-registration-free-com-objects