Español detenido por robar viagra: ¡el viagra o la vida!

¡Cómo está el mundo, Facundo! del periósquido de hoy:
 
Un español de 43 años ha sido detenido por atracar 10 farmacias en busca de viagra. La investigación comenzó el pasado mes de enero, cuando agentes del grupo XIII de la Brigada Provincial de Policía Judicial de Madrid tuvieron conocimiento de varios robos con intimidación en farmacias en los que el "modus operandi" era similar.


Un individuo accedía al local y, tras amenazar con una pistola, sustraía la recaudación y exigía que le entregaran todas las cajas de Viagra existentes en el establecimiento.
Como ejemplar de macho ibérico, quiero dejar claro que este caballero para nada es representativo de nuestro colectivo, y que la mayoría estamos firmes como una estaca sin ayuda de la farmacopea moderna.
 
 

Disable the crash dialog in VB6 (Visual Basic 6) with SetErrorMode()

If you don't want your Visual Basic 6 application to display the standard crash dialog, you can disable it by setting the SEM_NOGPFAULTERRORBOX flag in the process error mode.

The simple-minded way is just to do
 
SetErrorMode(SEM_NOGPFAULTERRORBOX);

but this overwrites the previous error mode rather than augmenting it. In other words, you inadvertently turned off the other error modes!

Unfortunately, there is no GetErrorMode function, so you have to do a double-shuffle.

 

Dim rc as Long rc = SetErrorMode(SEM_NOGPFAULTERRORBOX); SetErrorMode(rc Or SEM_NOGPFAULTERRORBOX);
 
It works perfectly with VB6 and is very useful if you have to call a buggy third-party component, or a user-provided plugin that you don't trust. You can set the error mode right before calling the buggy dll and setting it back immediatelly after.
 
Sample VB6 code that disables the crash dialog with SetErrorMode:
 
Private Sub Form_Load() Dim rc As Long rc = SetErrorMode(0) rc = SetErrorMode(rc Or SEM_NOGPFAULTERRORBOX) rc = SetUnhandledExceptionFilter(AddressOf UnhandledExceptionFilter) End Sub

SetUnhandledExceptionFilter usage with VB6

SetUnhandledExceptionFilter() doesn't seem to work very well with Visual Basic 6 (VB6). For some reason, no function or method calls are executed from within the exception handler, wich renders it almost useless. In C/C++ you can at least call functions and methods of the standard library. Therefore, unless someone proves me wrong, I believe that setting an unhandled exception handler with SetUnhandledExceptionFilter is pretty much useless in VB6.

Sample code that assigns an exception handler with SetUnhandledExceptionFilter that tries to turn the exception into a regular VB6 error. It doesn't work as expect for the reasons metioned above.

Option Explicit Public Declare Function SetUnhandledExceptionFilter Lib "kernel32" (ByVal lpTopKLevelExceptionFilter As Long) As Long Private Declare Sub CopyExceptionRecord Lib "kernel32" Alias "RtlMoveMemory" (pDest As EXCEPTION_RECORD, ByVal LPEXCEPTION_RECORD As Long, ByVal lngBytes As Long) Private Const EXCEPTION_MAXIMUM_PARAMETERS = 15 Private Type EXCEPTION_RECORD ExceptionCode As Long ExceptionFlags As Long pExceptionRecord As Long ExceptionAddress As Long NumberParameters As Long ExceptionInformation(EXCEPTION_MAXIMUM_PARAMETERS) As Long End Type Private Type EXCEPTION_DEBUG_INFO pExceptionRecord As Long dwFirstChance As Long End Type Private Type CONTEXT FltF0 As Double FltF1 As Double FltF2 As Double FltF3 As Double FltF4 As Double FltF5 As Double FltF6 As Double FltF7 As Double FltF8 As Double FltF9 As Double FltF10 As Double FltF11 As Double FltF12 As Double FltF13 As Double FltF14 As Double FltF15 As Double FltF16 As Double FltF17 As Double FltF18 As Double FltF19 As Double FltF20 As Double FltF21 As Double FltF22 As Double FltF23 As Double FltF24 As Double FltF25 As Double FltF26 As Double FltF27 As Double FltF28 As Double FltF29 As Double FltF30 As Double FltF31 As Double IntV0 As Double IntT0 As Double IntT1 As Double IntT2 As Double IntT3 As Double IntT4 As Double IntT5 As Double IntT6 As Double IntT7 As Double IntS0 As Double IntS1 As Double IntS2 As Double IntS3 As Double IntS4 As Double IntS5 As Double IntFp As Double IntA0 As Double IntA1 As Double IntA2 As Double IntA3 As Double IntA4 As Double IntA5 As Double IntT8 As Double IntT9 As Double IntT10 As Double IntT11 As Double IntRa As Double IntT12 As Double IntAt As Double IntGp As Double IntSp As Double IntZero As Double Fpcr As Double SoftFpcr As Double Fir As Double Psr As Long ContextFlags As Long Fill(4) As Long End Type Private Type EXCEPTION_POINTERS pExceptionRecord As EXCEPTION_RECORD ContextRecord As CONTEXT End Type Private Const EXCEPTION_EXECUTE_HANDLER = 1 Private Const EXCEPTION_DEBUG_EVENT = 1 Private Const EXCEPTION_CONTINUE_SEARCH = 0 Private Const EXCEPTION_CONTINUE_EXECUTION = -1 Private Function GetExceptionText(ByVal ExceptionCode As Long) As String 'This function receives an exception code value and returns the 'text description of the exception Select Case ExceptionCode ' Case EXCEPTION_ACCESS_VIOLATION ' GetExceptionText = "Access violation" ' Case EXCEPTION_DATATYPE_MISALIGNMENT ' GetExceptionText = "Data type misalignment" '...... '...... Case Else GetExceptionText = "Unknown (&H" & Right("00000000" & Hex(ExceptionCode), 8) & ")" End Select End Function Public Function UnhandledExceptionFilter(ByRef ExceptionPtrs As EXCEPTION_POINTERS) As Long Dim Rec As EXCEPTION_RECORD, ExceptionText As String 'Get the current exception record. Rec = ExceptionPtrs.pExceptionRecord 'If Rec.pExceptionRecord is not zero, then it is a nested exception and Rec.pExceptionRecord points to another EXCEPTION_RECORD structure. Follow the pointers back to the original exception. Do Until Rec.pExceptionRecord = 0 CopyExceptionRecord Rec, Rec.pExceptionRecord, Len(Rec) Loop Beep 'Translate the exception code into a user-friendly string. ExceptionText = GetExceptionText(Rec.ExceptionCode) 'Turn Win32 error into normal VBA error Err.Raise Rec.ExceptionCode, "ExceptionFilter.UnhandledExceptionFilter", ExceptionText UnhandledExceptionFilter = EXCEPTION_CONTINUE_SEARCH

A high performance alternative to Dictionary and Collection: Treaps in Visual Basic (VB6)

VB6 Collection Performance

 

The Collection is the single data structure provided by VB5 and VB6, and was designed with the “one size fits all” philosophy. It allows you to access the elements in it by a key and also sequentially, and as most multi-use tools, doesn’t perform very well in either scenario.

 

Much worse than the performance issues, are the serious limitations in Collection: as soon as you add a key, there’s no way to change it, and even worse, there’s no way to know which keys have been entered.

 

Dictionary

 

 

 The Dictionary object came with the MS Scripting runtime dll and provides a much better implementation than the Collection. Even though much better than the humble Collection, Dictionary’s iteration methods are still a bit primitive and wasteful (from a performance point of view) when it contains many items.

 

While delivering applications that used Dictionary (EasyJob Resume Builder http://www.easyjob.net), I encountered several serious issues that forced me to ditch it:

 

·         The MS Scripting Runtime dll (sccrun.dll) wasn’t correctly registering in some systems, making the app crash.

·         On some systems, the creation of a Dictionary object was being blocked by over enthusiastic security software that tried to prevent any script from running.

 

Enter the Treap

 

(hardcore nerd-talk ahead: you may skip this section if you want)

 

I have no idea how the Dictionary or Collection are implemented, but they are probably based on a Balanced Binary Tree or a Hash Table.

 

The Treap is also a Binary Balanced Tree, but with a twist that makes it very simple (if compared to other BBT’s, such as AVL Trees or Red-Black Trees) and very efficient in terms of both speed and memory.

 

AVL and Red-Black trees are cool, because they guarantee O(log n) insert, lookup and deletion time, but are complicated to implement, as their rebalancing routines are complex.  However, if we are willing to accept a probabilistic assurance of good performance, Treaps provide a much simpler solution.

The stroke of genius behind the Treap is to use randomness to keep a binary tree balanced. Binary search trees are great as long as they remain balanced. But if the elements are inserted in order, then the tree will turn into a linked list with very poor O(log n) performance. On the other hand if the elements are inserted in random order, then the tree will remain balanced.

 

So here’s the magic cookie: no matter how you add the elements to the Treap, it will have the same structure it would have if the elements had been inserted in random order into a binary search tree.

 

The Treap achieves this by using a random priority field in every node. The Treap behaves as a binary search tree with respect to the keys in the nodes, and also as a Heap with respect to the priorities. Hence the name: Treap = Tree + Heap.

 

The algorithm to insert a new node is similar to that of red-black trees:

1.      Find the unique leaf where the node can be inserted while preserving the Binary Search Tree property.

2.      Perform a series of tree rotations to satisfy the Heap ordering property.

 

Treap for Visual Basic 6

 

The main class is CTreap.

 

Values can be anything you can put into a Variant (strings, longs, singles, objects, other Treaps, whatever).

Keys can be almost anything, except Arrays: dates, strings, numbers, objects, etc….

If you try to add an Array as a key, you will get a Wrong Key Type error.

 

Methods

 

add(ByVal aKey As Variant, ByRef aValue As Variant) As Boolean

 

Adds a value to the Treap. Unlike a Collection, the key is mandatory. Returns true if the key wasn’t already present and returns false if the key was already present (it won’t add the value in this case).

 

clear()

 

Zaps the whole Treap, leaving it empty.

 

getValue(ByVal aKey As Variant, ByRef aValue As Variant) As Boolean

 

Retrieve a value by its key.

Since VB's assignment syntax is different for objects and non-objects, you can't just return the value, as the user won't know, a priori, which syntax (set x = y or x = y) to use. So we take a ByRef parameter and assign it to the value. This way the utter ugliness remains relatively hidden.

 

Whoever designed this should be sent to Abu Graib.

 

Returns true if the value was found, and false if it was not found.

setValue(ByVal aKey As Variant, ByVal aNewValue As Variant) As Boolean

 

Sets the new value for an existing node. Returns True if the node exists, and False if it doesn't.

 

changeKey(ByVal oldKey As Variant, ByVal newKey As Variant) As Boolean

 

Change the key of an existing node. If the node exists, return true, otherwise, return false.

 

exists(ByVal aKey As Variant) As Boolean

 

Detects the presence of a key.

 

isEmpty() As Boolean

 

Returns True if the Treap is empty.

 

remove(ByVal aKey As Variant)

 

Remove an element.

 

Keys(Optional ascendingOrder As Boolean = True) As IIterator

 

This is quite different from Collection and Dictionary. It returns an instance of CKeyIterator ( a class that implements the IIterator interface).

 

The only methods of CKeyIterator that you have to worry about are hasMore() (returns True until you reach the last key in the Treap) and getItem(item As Variant).

 

Example:

 

‘Iterate through the keys forwards and backwards

‘at the same time

 

Dim vKey As Variant

Dim rForwards As IIterator

Dim rBackwards As IIterator

 

 

Set rForwards = m_rtreap.keys(True)

Set rBackwards = m_rtreap.keys(False)

 

Do While rForwards.hasMore

    Call rForwards.getItem(vKey)

    Debug.Print CStr(vKey)

    Call rBackwards.getItem(vKey)

    Debug.Print CStr(vKey)

Loop

 

Values(Optional ascendingOrder As Boolean = True) As IIterator

 

Similar to Keys(). Returns an instance of CValueIterator. Allows you to iterate the values in a Treap.

Properties

 

Count

 

Read only. Returns the number of elements in the Treap.

 

Events

 

If you declare it with withevents, you can observe the changes in the treap with these events:

 

Public Event onAdd(ByVal Sender As CTreap,

         ByVal newKey As Variant,

         ByVal newValue As Variant)

 

Public Event onKeyChange(ByVal Sender As CTreap,

ByVal oldKey As Variant,

ByVal newKey As Variant)

 

Public Event onValueChange(ByVal Sender As CTreap,

ByVal Key As Variant,

ByVal newValue As Variant)

 

Public Event onRemove(ByVal Sender As CTreap,

  ByVal oldKey As Variant)

 

Public Event onEmpty(ByVal Sender As CTreap)

 

 

 

Contact

 

If you find any bugs ore have any suggestions, please drop me a line.