").append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+ // Otherwise use the full result
+ responseText );
+
+ }).complete( callback && function( jqXHR, status ) {
+ self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+ });
+ }
+
+ return this;
+};
+
+
+
+
+jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+};
+
+
+
+
+
+var docElem = window.document.documentElement;
+
+/**
+ * Gets a window from an element
+ */
+function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+}
+
+jQuery.offset = {
+ setOffset: function( elem, options, i ) {
+ var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
+ position = jQuery.css( elem, "position" ),
+ curElem = jQuery( elem ),
+ props = {};
+
+ // set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ curOffset = curElem.offset();
+ curCSSTop = jQuery.css( elem, "top" );
+ curCSSLeft = jQuery.css( elem, "left" );
+ calculatePosition = ( position === "absolute" || position === "fixed" ) &&
+ jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;
+
+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+jQuery.fn.extend({
+ offset: function( options ) {
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ var docElem, win,
+ box = { top: 0, left: 0 },
+ elem = this[ 0 ],
+ doc = elem && elem.ownerDocument;
+
+ if ( !doc ) {
+ return;
+ }
+
+ docElem = doc.documentElement;
+
+ // Make sure it's not a disconnected DOM node
+ if ( !jQuery.contains( docElem, elem ) ) {
+ return box;
+ }
+
+ // If we don't have gBCR, just use 0,0 rather than error
+ // BlackBerry 5, iOS 3 (original iPhone)
+ if ( typeof elem.getBoundingClientRect !== strundefined ) {
+ box = elem.getBoundingClientRect();
+ }
+ win = getWindow( doc );
+ return {
+ top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
+ left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
+ };
+ },
+
+ position: function() {
+ if ( !this[ 0 ] ) {
+ return;
+ }
+
+ var offsetParent, offset,
+ parentOffset = { top: 0, left: 0 },
+ elem = this[ 0 ];
+
+ // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
+ // we assume that getBoundingClientRect is available when computed position is fixed
+ offset = elem.getBoundingClientRect();
+ } else {
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent();
+
+ // Get correct offsets
+ offset = this.offset();
+ if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+ parentOffset = offsetParent.offset();
+ }
+
+ // Add offsetParent borders
+ parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+ parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+ }
+
+ // Subtract parent offsets and element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ return {
+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
+ };
+ },
+
+ offsetParent: function() {
+ return this.map(function() {
+ var offsetParent = this.offsetParent || docElem;
+
+ while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent || docElem;
+ });
+ }
+});
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
+ var top = /Y/.test( prop );
+
+ jQuery.fn[ method ] = function( val ) {
+ return access( this, function( elem, method, val ) {
+ var win = getWindow( elem );
+
+ if ( val === undefined ) {
+ return win ? (prop in win) ? win[ prop ] :
+ win.document.documentElement[ method ] :
+ elem[ method ];
+ }
+
+ if ( win ) {
+ win.scrollTo(
+ !top ? val : jQuery( win ).scrollLeft(),
+ top ? val : jQuery( win ).scrollTop()
+ );
+
+ } else {
+ elem[ method ] = val;
+ }
+ }, method, val, arguments.length, null );
+ };
+});
+
+// Add the top/left cssHooks using jQuery.fn.position
+// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+// getComputedStyle returns percent when specified for top/left/bottom/right
+// rather than make the css module depend on the offset module, we just check for it here
+jQuery.each( [ "top", "left" ], function( i, prop ) {
+ jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
+ function( elem, computed ) {
+ if ( computed ) {
+ computed = curCSS( elem, prop );
+ // if curCSS returns percentage, fallback to offset
+ return rnumnonpx.test( computed ) ?
+ jQuery( elem ).position()[ prop ] + "px" :
+ computed;
+ }
+ }
+ );
+});
+
+
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+ // margin is only for outerHeight, outerWidth
+ jQuery.fn[ funcName ] = function( margin, value ) {
+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+ return access( this, function( elem, type, value ) {
+ var doc;
+
+ if ( jQuery.isWindow( elem ) ) {
+ // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+ // isn't a whole lot we can do. See pull request at this URL for discussion:
+ // https://github.com/jquery/jquery/pull/764
+ return elem.document.documentElement[ "client" + name ];
+ }
+
+ // Get document width or height
+ if ( elem.nodeType === 9 ) {
+ doc = elem.documentElement;
+
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
+ // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
+ return Math.max(
+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+ elem.body[ "offset" + name ], doc[ "offset" + name ],
+ doc[ "client" + name ]
+ );
+ }
+
+ return value === undefined ?
+ // Get width or height on the element, requesting but not forcing parseFloat
+ jQuery.css( elem, type, extra ) :
+
+ // Set width or height on the element
+ jQuery.style( elem, type, value, extra );
+ }, type, chainable ? margin : undefined, chainable, null );
+ };
+ });
+});
+
+
+// The number of elements contained in the matched element set
+jQuery.fn.size = function() {
+ return this.length;
+};
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+
+
+
+// Register as a named AMD module, since jQuery can be concatenated with other
+// files that may use define, but not via a proper concatenation script that
+// understands anonymous AMD modules. A named AMD is safest and most robust
+// way to register. Lowercase jquery is used because AMD module names are
+// derived from file names, and jQuery is normally delivered in a lowercase
+// file name. Do this after creating the global so that if an AMD module wants
+// to call noConflict to hide this version of jQuery, it will work.
+
+// Note that for maximum portability, libraries that are not jQuery should
+// declare themselves as anonymous modules, and avoid setting a global if an
+// AMD loader is present. jQuery is a special case. For more information, see
+// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
+
+if ( typeof define === "function" && define.amd ) {
+ define( "jquery", [], function() {
+ return jQuery;
+ });
+}
+
+
+
+
+var
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$;
+
+jQuery.noConflict = function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+};
+
+// Expose jQuery and $ identifiers, even in
+// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
+// and CommonJS for browser emulators (#13566)
+if ( typeof noGlobal === strundefined ) {
+ window.jQuery = window.$ = jQuery;
+}
+
+
+
+
+return jQuery;
+
+}));
diff --git a/docs/build/html/_static/jquery.js b/docs/build/html/_static/jquery.js
new file mode 100644
index 0000000..ab28a24
--- /dev/null
+++ b/docs/build/html/_static/jquery.js
@@ -0,0 +1,4 @@
+/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="
",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="
",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++d
b;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML=" ","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML=" ",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;
+if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML=" a ",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML=" ",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h ]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/\s*$/g,rb={option:[1,""," "],legend:[1,""," "],area:[1,""," "],param:[1,""," "],thead:[1,""],tr:[2,""],col:[2,""],td:[3,""],_default:k.htmlSerialize?[0,"",""]:[1,"X","
"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1>$2>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?""!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1>$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("")).appendTo(b.documentElement),b=(Cb[0].contentWindow||Cb[0].contentDocument).document,b.write(),b.close(),c=Eb(a,b),Cb.detach()),Db[a]=c),c}!function(){var a;k.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,d;return c=y.getElementsByTagName("body")[0],c&&c.style?(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(y.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(d),a):void 0}}();var Gb=/^margin/,Hb=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ib,Jb,Kb=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ib=function(a){return a.ownerDocument.defaultView.getComputedStyle(a,null)},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||m.contains(a.ownerDocument,a)||(g=m.style(a,b)),Hb.test(g)&&Gb.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0===g?g:g+""}):y.documentElement.currentStyle&&(Ib=function(a){return a.currentStyle},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Hb.test(g)&&!Kb.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Lb(a,b){return{get:function(){var c=a();if(null!=c)return c?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d,e,f,g,h;if(b=y.createElement("div"),b.innerHTML=" a ",d=b.getElementsByTagName("a")[0],c=d&&d.style){c.cssText="float:left;opacity:.5",k.opacity="0.5"===c.opacity,k.cssFloat=!!c.cssFloat,b.style.backgroundClip="content-box",b.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===b.style.backgroundClip,k.boxSizing=""===c.boxSizing||""===c.MozBoxSizing||""===c.WebkitBoxSizing,m.extend(k,{reliableHiddenOffsets:function(){return null==g&&i(),g},boxSizingReliable:function(){return null==f&&i(),f},pixelPosition:function(){return null==e&&i(),e},reliableMarginRight:function(){return null==h&&i(),h}});function i(){var b,c,d,i;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),b.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",e=f=!1,h=!0,a.getComputedStyle&&(e="1%"!==(a.getComputedStyle(b,null)||{}).top,f="4px"===(a.getComputedStyle(b,null)||{width:"4px"}).width,i=b.appendChild(y.createElement("div")),i.style.cssText=b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",i.style.marginRight=i.style.width="0",b.style.width="1px",h=!parseFloat((a.getComputedStyle(i,null)||{}).marginRight)),b.innerHTML="",i=b.getElementsByTagName("td"),i[0].style.cssText="margin:0;border:0;padding:0;display:none",g=0===i[0].offsetHeight,g&&(i[0].style.display="",i[1].style.display="none",g=0===i[0].offsetHeight),c.removeChild(d))}}}(),m.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var Mb=/alpha\([^)]*\)/i,Nb=/opacity\s*=\s*([^)]*)/,Ob=/^(none|table(?!-c[ea]).+)/,Pb=new RegExp("^("+S+")(.*)$","i"),Qb=new RegExp("^([+-])=("+S+")","i"),Rb={position:"absolute",visibility:"hidden",display:"block"},Sb={letterSpacing:"0",fontWeight:"400"},Tb=["Webkit","O","Moz","ms"];function Ub(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=Tb.length;while(e--)if(b=Tb[e]+c,b in a)return b;return d}function Vb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=m._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&U(d)&&(f[g]=m._data(d,"olddisplay",Fb(d.nodeName)))):(e=U(d),(c&&"none"!==c||!e)&&m._data(d,"olddisplay",e?c:m.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function Wb(a,b,c){var d=Pb.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Xb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=m.css(a,c+T[f],!0,e)),d?("content"===c&&(g-=m.css(a,"padding"+T[f],!0,e)),"margin"!==c&&(g-=m.css(a,"border"+T[f]+"Width",!0,e))):(g+=m.css(a,"padding"+T[f],!0,e),"padding"!==c&&(g+=m.css(a,"border"+T[f]+"Width",!0,e)));return g}function Yb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ib(a),g=k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Jb(a,b,f),(0>e||null==e)&&(e=a.style[b]),Hb.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Xb(a,b,c||(g?"border":"content"),d,f)+"px"}m.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Jb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":k.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=m.camelCase(b),i=a.style;if(b=m.cssProps[h]||(m.cssProps[h]=Ub(i,h)),g=m.cssHooks[b]||m.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=Qb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(m.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||m.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=m.camelCase(b);return b=m.cssProps[h]||(m.cssProps[h]=Ub(a.style,h)),g=m.cssHooks[b]||m.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Jb(a,b,d)),"normal"===f&&b in Sb&&(f=Sb[b]),""===c||c?(e=parseFloat(f),c===!0||m.isNumeric(e)?e||0:f):f}}),m.each(["height","width"],function(a,b){m.cssHooks[b]={get:function(a,c,d){return c?Ob.test(m.css(a,"display"))&&0===a.offsetWidth?m.swap(a,Rb,function(){return Yb(a,b,d)}):Yb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ib(a);return Wb(a,c,d?Xb(a,b,d,k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,e),e):0)}}}),k.opacity||(m.cssHooks.opacity={get:function(a,b){return Nb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=m.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===m.trim(f.replace(Mb,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Mb.test(f)?f.replace(Mb,e):f+" "+e)}}),m.cssHooks.marginRight=Lb(k.reliableMarginRight,function(a,b){return b?m.swap(a,{display:"inline-block"},Jb,[a,"marginRight"]):void 0}),m.each({margin:"",padding:"",border:"Width"},function(a,b){m.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+T[d]+b]=f[d]||f[d-2]||f[0];return e}},Gb.test(a)||(m.cssHooks[a+b].set=Wb)}),m.fn.extend({css:function(a,b){return V(this,function(a,b,c){var d,e,f={},g=0;if(m.isArray(b)){for(d=Ib(a),e=b.length;e>g;g++)f[b[g]]=m.css(a,b[g],!1,d);return f}return void 0!==c?m.style(a,b,c):m.css(a,b)},a,b,arguments.length>1)},show:function(){return Vb(this,!0)},hide:function(){return Vb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){U(this)?m(this).show():m(this).hide()})}});function Zb(a,b,c,d,e){return new Zb.prototype.init(a,b,c,d,e)}m.Tween=Zb,Zb.prototype={constructor:Zb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(m.cssNumber[c]?"":"px")
+},cur:function(){var a=Zb.propHooks[this.prop];return a&&a.get?a.get(this):Zb.propHooks._default.get(this)},run:function(a){var b,c=Zb.propHooks[this.prop];return this.pos=b=this.options.duration?m.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Zb.propHooks._default.set(this),this}},Zb.prototype.init.prototype=Zb.prototype,Zb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=m.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){m.fx.step[a.prop]?m.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[m.cssProps[a.prop]]||m.cssHooks[a.prop])?m.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Zb.propHooks.scrollTop=Zb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},m.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},m.fx=Zb.prototype.init,m.fx.step={};var $b,_b,ac=/^(?:toggle|show|hide)$/,bc=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),cc=/queueHooks$/,dc=[ic],ec={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=bc.exec(b),f=e&&e[3]||(m.cssNumber[a]?"":"px"),g=(m.cssNumber[a]||"px"!==f&&+d)&&bc.exec(m.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,m.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function fc(){return setTimeout(function(){$b=void 0}),$b=m.now()}function gc(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=T[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function hc(a,b,c){for(var d,e=(ec[b]||[]).concat(ec["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ic(a,b,c){var d,e,f,g,h,i,j,l,n=this,o={},p=a.style,q=a.nodeType&&U(a),r=m._data(a,"fxshow");c.queue||(h=m._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,n.always(function(){n.always(function(){h.unqueued--,m.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=m.css(a,"display"),l="none"===j?m._data(a,"olddisplay")||Fb(a.nodeName):j,"inline"===l&&"none"===m.css(a,"float")&&(k.inlineBlockNeedsLayout&&"inline"!==Fb(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",k.shrinkWrapBlocks()||n.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],ac.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||m.style(a,d)}else j=void 0;if(m.isEmptyObject(o))"inline"===("none"===j?Fb(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=m._data(a,"fxshow",{}),f&&(r.hidden=!q),q?m(a).show():n.done(function(){m(a).hide()}),n.done(function(){var b;m._removeData(a,"fxshow");for(b in o)m.style(a,b,o[b])});for(d in o)g=hc(q?r[d]:0,d,n),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function jc(a,b){var c,d,e,f,g;for(c in a)if(d=m.camelCase(c),e=b[d],f=a[c],m.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=m.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kc(a,b,c){var d,e,f=0,g=dc.length,h=m.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=$b||fc(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:m.extend({},b),opts:m.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:$b||fc(),duration:c.duration,tweens:[],createTween:function(b,c){var d=m.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(jc(k,j.opts.specialEasing);g>f;f++)if(d=dc[f].call(j,a,k,j.opts))return d;return m.map(k,hc,j),m.isFunction(j.opts.start)&&j.opts.start.call(a,j),m.fx.timer(m.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}m.Animation=m.extend(kc,{tweener:function(a,b){m.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],ec[c]=ec[c]||[],ec[c].unshift(b)},prefilter:function(a,b){b?dc.unshift(a):dc.push(a)}}),m.speed=function(a,b,c){var d=a&&"object"==typeof a?m.extend({},a):{complete:c||!c&&b||m.isFunction(a)&&a,duration:a,easing:c&&b||b&&!m.isFunction(b)&&b};return d.duration=m.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in m.fx.speeds?m.fx.speeds[d.duration]:m.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){m.isFunction(d.old)&&d.old.call(this),d.queue&&m.dequeue(this,d.queue)},d},m.fn.extend({fadeTo:function(a,b,c,d){return this.filter(U).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=m.isEmptyObject(a),f=m.speed(b,c,d),g=function(){var b=kc(this,m.extend({},a),f);(e||m._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=m.timers,g=m._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&cc.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&m.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=m._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=m.timers,g=d?d.length:0;for(c.finish=!0,m.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),m.each(["toggle","show","hide"],function(a,b){var c=m.fn[b];m.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(gc(b,!0),a,d,e)}}),m.each({slideDown:gc("show"),slideUp:gc("hide"),slideToggle:gc("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){m.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),m.timers=[],m.fx.tick=function(){var a,b=m.timers,c=0;for($b=m.now();ca ",d=b.getElementsByTagName("a")[0],c=y.createElement("select"),e=c.appendChild(y.createElement("option")),a=b.getElementsByTagName("input")[0],d.style.cssText="top:1px",k.getSetAttribute="t"!==b.className,k.style=/top/.test(d.getAttribute("style")),k.hrefNormalized="/a"===d.getAttribute("href"),k.checkOn=!!a.value,k.optSelected=e.selected,k.enctype=!!y.createElement("form").enctype,c.disabled=!0,k.optDisabled=!e.disabled,a=y.createElement("input"),a.setAttribute("value",""),k.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),k.radioValue="t"===a.value}();var lc=/\r/g;m.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=m.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,m(this).val()):a,null==e?e="":"number"==typeof e?e+="":m.isArray(e)&&(e=m.map(e,function(a){return null==a?"":a+""})),b=m.valHooks[this.type]||m.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=m.valHooks[e.type]||m.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(lc,""):null==c?"":c)}}}),m.extend({valHooks:{option:{get:function(a){var b=m.find.attr(a,"value");return null!=b?b:m.trim(m.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&m.nodeName(c.parentNode,"optgroup"))){if(b=m(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=m.makeArray(b),g=e.length;while(g--)if(d=e[g],m.inArray(m.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),m.each(["radio","checkbox"],function(){m.valHooks[this]={set:function(a,b){return m.isArray(b)?a.checked=m.inArray(m(a).val(),b)>=0:void 0}},k.checkOn||(m.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var mc,nc,oc=m.expr.attrHandle,pc=/^(?:checked|selected)$/i,qc=k.getSetAttribute,rc=k.input;m.fn.extend({attr:function(a,b){return V(this,m.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){m.removeAttr(this,a)})}}),m.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===K?m.prop(a,b,c):(1===f&&m.isXMLDoc(a)||(b=b.toLowerCase(),d=m.attrHooks[b]||(m.expr.match.bool.test(b)?nc:mc)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=m.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void m.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=m.propFix[c]||c,m.expr.match.bool.test(c)?rc&&qc||!pc.test(c)?a[d]=!1:a[m.camelCase("default-"+c)]=a[d]=!1:m.attr(a,c,""),a.removeAttribute(qc?c:d)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&m.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),nc={set:function(a,b,c){return b===!1?m.removeAttr(a,c):rc&&qc||!pc.test(c)?a.setAttribute(!qc&&m.propFix[c]||c,c):a[m.camelCase("default-"+c)]=a[c]=!0,c}},m.each(m.expr.match.bool.source.match(/\w+/g),function(a,b){var c=oc[b]||m.find.attr;oc[b]=rc&&qc||!pc.test(b)?function(a,b,d){var e,f;return d||(f=oc[b],oc[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,oc[b]=f),e}:function(a,b,c){return c?void 0:a[m.camelCase("default-"+b)]?b.toLowerCase():null}}),rc&&qc||(m.attrHooks.value={set:function(a,b,c){return m.nodeName(a,"input")?void(a.defaultValue=b):mc&&mc.set(a,b,c)}}),qc||(mc={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},oc.id=oc.name=oc.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},m.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:mc.set},m.attrHooks.contenteditable={set:function(a,b,c){mc.set(a,""===b?!1:b,c)}},m.each(["width","height"],function(a,b){m.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),k.style||(m.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var sc=/^(?:input|select|textarea|button|object)$/i,tc=/^(?:a|area)$/i;m.fn.extend({prop:function(a,b){return V(this,m.prop,a,b,arguments.length>1)},removeProp:function(a){return a=m.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),m.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!m.isXMLDoc(a),f&&(b=m.propFix[b]||b,e=m.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=m.find.attr(a,"tabindex");return b?parseInt(b,10):sc.test(a.nodeName)||tc.test(a.nodeName)&&a.href?0:-1}}}}),k.hrefNormalized||m.each(["href","src"],function(a,b){m.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),k.optSelected||(m.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),m.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){m.propFix[this.toLowerCase()]=this}),k.enctype||(m.propFix.enctype="encoding");var uc=/[\t\r\n\f]/g;m.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j="string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).addClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=m.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j=0===arguments.length||"string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).removeClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?m.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(m.isFunction(a)?function(c){m(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=m(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===K||"boolean"===c)&&(this.className&&m._data(this,"__className__",this.className),this.className=this.className||a===!1?"":m._data(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(uc," ").indexOf(b)>=0)return!0;return!1}}),m.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){m.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),m.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var vc=m.now(),wc=/\?/,xc=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;m.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=m.trim(b+"");return e&&!m.trim(e.replace(xc,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():m.error("Invalid JSON: "+b)},m.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||m.error("Invalid XML: "+b),c};var yc,zc,Ac=/#.*$/,Bc=/([?&])_=[^&]*/,Cc=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Dc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Ec=/^(?:GET|HEAD)$/,Fc=/^\/\//,Gc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Hc={},Ic={},Jc="*/".concat("*");try{zc=location.href}catch(Kc){zc=y.createElement("a"),zc.href="",zc=zc.href}yc=Gc.exec(zc.toLowerCase())||[];function Lc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(m.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Mc(a,b,c,d){var e={},f=a===Ic;function g(h){var i;return e[h]=!0,m.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Nc(a,b){var c,d,e=m.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&m.extend(!0,a,c),a}function Oc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Pc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}m.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:zc,type:"GET",isLocal:Dc.test(yc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Jc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":m.parseJSON,"text xml":m.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Nc(Nc(a,m.ajaxSettings),b):Nc(m.ajaxSettings,a)},ajaxPrefilter:Lc(Hc),ajaxTransport:Lc(Ic),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=m.ajaxSetup({},b),l=k.context||k,n=k.context&&(l.nodeType||l.jquery)?m(l):m.event,o=m.Deferred(),p=m.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!j){j={};while(b=Cc.exec(f))j[b[1].toLowerCase()]=b[2]}b=j[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return i&&i.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||zc)+"").replace(Ac,"").replace(Fc,yc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=m.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(c=Gc.exec(k.url.toLowerCase()),k.crossDomain=!(!c||c[1]===yc[1]&&c[2]===yc[2]&&(c[3]||("http:"===c[1]?"80":"443"))===(yc[3]||("http:"===yc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=m.param(k.data,k.traditional)),Mc(Hc,k,b,v),2===t)return v;h=k.global,h&&0===m.active++&&m.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!Ec.test(k.type),e=k.url,k.hasContent||(k.data&&(e=k.url+=(wc.test(e)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=Bc.test(e)?e.replace(Bc,"$1_="+vc++):e+(wc.test(e)?"&":"?")+"_="+vc++)),k.ifModified&&(m.lastModified[e]&&v.setRequestHeader("If-Modified-Since",m.lastModified[e]),m.etag[e]&&v.setRequestHeader("If-None-Match",m.etag[e])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+Jc+"; q=0.01":""):k.accepts["*"]);for(d in k.headers)v.setRequestHeader(d,k.headers[d]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(d in{success:1,error:1,complete:1})v[d](k[d]);if(i=Mc(Ic,k,b,v)){v.readyState=1,h&&n.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,i.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,c,d){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),i=void 0,f=d||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,c&&(u=Oc(k,v,c)),u=Pc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(m.lastModified[e]=w),w=v.getResponseHeader("etag"),w&&(m.etag[e]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,h&&n.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),h&&(n.trigger("ajaxComplete",[v,k]),--m.active||m.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return m.get(a,b,c,"json")},getScript:function(a,b){return m.get(a,void 0,b,"script")}}),m.each(["get","post"],function(a,b){m[b]=function(a,c,d,e){return m.isFunction(c)&&(e=e||d,d=c,c=void 0),m.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),m.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){m.fn[b]=function(a){return this.on(b,a)}}),m._evalUrl=function(a){return m.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},m.fn.extend({wrapAll:function(a){if(m.isFunction(a))return this.each(function(b){m(this).wrapAll(a.call(this,b))});if(this[0]){var b=m(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(m.isFunction(a)?function(b){m(this).wrapInner(a.call(this,b))}:function(){var b=m(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=m.isFunction(a);return this.each(function(c){m(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){m.nodeName(this,"body")||m(this).replaceWith(this.childNodes)}).end()}}),m.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!k.reliableHiddenOffsets()&&"none"===(a.style&&a.style.display||m.css(a,"display"))},m.expr.filters.visible=function(a){return!m.expr.filters.hidden(a)};var Qc=/%20/g,Rc=/\[\]$/,Sc=/\r?\n/g,Tc=/^(?:submit|button|image|reset|file)$/i,Uc=/^(?:input|select|textarea|keygen)/i;function Vc(a,b,c,d){var e;if(m.isArray(b))m.each(b,function(b,e){c||Rc.test(a)?d(a,e):Vc(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==m.type(b))d(a,b);else for(e in b)Vc(a+"["+e+"]",b[e],c,d)}m.param=function(a,b){var c,d=[],e=function(a,b){b=m.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=m.ajaxSettings&&m.ajaxSettings.traditional),m.isArray(a)||a.jquery&&!m.isPlainObject(a))m.each(a,function(){e(this.name,this.value)});else for(c in a)Vc(c,a[c],b,e);return d.join("&").replace(Qc,"+")},m.fn.extend({serialize:function(){return m.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=m.prop(this,"elements");return a?m.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!m(this).is(":disabled")&&Uc.test(this.nodeName)&&!Tc.test(a)&&(this.checked||!W.test(a))}).map(function(a,b){var c=m(this).val();return null==c?null:m.isArray(c)?m.map(c,function(a){return{name:b.name,value:a.replace(Sc,"\r\n")}}):{name:b.name,value:c.replace(Sc,"\r\n")}}).get()}}),m.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&Zc()||$c()}:Zc;var Wc=0,Xc={},Yc=m.ajaxSettings.xhr();a.ActiveXObject&&m(a).on("unload",function(){for(var a in Xc)Xc[a](void 0,!0)}),k.cors=!!Yc&&"withCredentials"in Yc,Yc=k.ajax=!!Yc,Yc&&m.ajaxTransport(function(a){if(!a.crossDomain||k.cors){var b;return{send:function(c,d){var e,f=a.xhr(),g=++Wc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)void 0!==c[e]&&f.setRequestHeader(e,c[e]+"");f.send(a.hasContent&&a.data||null),b=function(c,e){var h,i,j;if(b&&(e||4===f.readyState))if(delete Xc[g],b=void 0,f.onreadystatechange=m.noop,e)4!==f.readyState&&f.abort();else{j={},h=f.status,"string"==typeof f.responseText&&(j.text=f.responseText);try{i=f.statusText}catch(k){i=""}h||!a.isLocal||a.crossDomain?1223===h&&(h=204):h=j.text?200:404}j&&d(h,i,j,f.getAllResponseHeaders())},a.async?4===f.readyState?setTimeout(b):f.onreadystatechange=Xc[g]=b:b()},abort:function(){b&&b(void 0,!0)}}}});function Zc(){try{return new a.XMLHttpRequest}catch(b){}}function $c(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}m.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return m.globalEval(a),a}}}),m.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),m.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=y.head||m("head")[0]||y.documentElement;return{send:function(d,e){b=y.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||e(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var _c=[],ad=/(=)\?(?=&|$)|\?\?/;m.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=_c.pop()||m.expando+"_"+vc++;return this[a]=!0,a}}),m.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(ad.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&ad.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=m.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(ad,"$1"+e):b.jsonp!==!1&&(b.url+=(wc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||m.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,_c.push(e)),g&&m.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),m.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||y;var d=u.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=m.buildFragment([a],b,e),e&&e.length&&m(e).remove(),m.merge([],d.childNodes))};var bd=m.fn.load;m.fn.load=function(a,b,c){if("string"!=typeof a&&bd)return bd.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=m.trim(a.slice(h,a.length)),a=a.slice(0,h)),m.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(f="POST"),g.length>0&&m.ajax({url:a,type:f,dataType:"html",data:b}).done(function(a){e=arguments,g.html(d?m("").append(m.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},m.expr.filters.animated=function(a){return m.grep(m.timers,function(b){return a===b.elem}).length};var cd=a.document.documentElement;function dd(a){return m.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}m.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=m.css(a,"position"),l=m(a),n={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=m.css(a,"top"),i=m.css(a,"left"),j=("absolute"===k||"fixed"===k)&&m.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),m.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(n.top=b.top-h.top+g),null!=b.left&&(n.left=b.left-h.left+e),"using"in b?b.using.call(a,n):l.css(n)}},m.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){m.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,m.contains(b,e)?(typeof e.getBoundingClientRect!==K&&(d=e.getBoundingClientRect()),c=dd(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===m.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),m.nodeName(a[0],"html")||(c=a.offset()),c.top+=m.css(a[0],"borderTopWidth",!0),c.left+=m.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-m.css(d,"marginTop",!0),left:b.left-c.left-m.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||cd;while(a&&!m.nodeName(a,"html")&&"static"===m.css(a,"position"))a=a.offsetParent;return a||cd})}}),m.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);m.fn[a]=function(d){return V(this,function(a,d,e){var f=dd(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?m(f).scrollLeft():e,c?e:m(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),m.each(["top","left"],function(a,b){m.cssHooks[b]=Lb(k.pixelPosition,function(a,c){return c?(c=Jb(a,b),Hb.test(c)?m(a).position()[b]+"px":c):void 0})}),m.each({Height:"height",Width:"width"},function(a,b){m.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){m.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return V(this,function(b,c,d){var e;return m.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?m.css(b,c,g):m.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),m.fn.size=function(){return this.length},m.fn.andSelf=m.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return m});var ed=a.jQuery,fd=a.$;return m.noConflict=function(b){return a.$===m&&(a.$=fd),b&&a.jQuery===m&&(a.jQuery=ed),m},typeof b===K&&(a.jQuery=a.$=m),m});
diff --git a/docs/build/html/_static/minus.png b/docs/build/html/_static/minus.png
new file mode 100644
index 0000000..0f22b16
Binary files /dev/null and b/docs/build/html/_static/minus.png differ
diff --git a/docs/build/html/_static/plus.png b/docs/build/html/_static/plus.png
new file mode 100644
index 0000000..0cfe084
Binary files /dev/null and b/docs/build/html/_static/plus.png differ
diff --git a/docs/build/html/_static/pygments.css b/docs/build/html/_static/pygments.css
new file mode 100644
index 0000000..8213e90
--- /dev/null
+++ b/docs/build/html/_static/pygments.css
@@ -0,0 +1,65 @@
+.highlight .hll { background-color: #ffffcc }
+.highlight { background: #eeffcc; }
+.highlight .c { color: #408090; font-style: italic } /* Comment */
+.highlight .err { border: 1px solid #FF0000 } /* Error */
+.highlight .k { color: #007020; font-weight: bold } /* Keyword */
+.highlight .o { color: #666666 } /* Operator */
+.highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */
+.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
+.highlight .cp { color: #007020 } /* Comment.Preproc */
+.highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */
+.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
+.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
+.highlight .gd { color: #A00000 } /* Generic.Deleted */
+.highlight .ge { font-style: italic } /* Generic.Emph */
+.highlight .gr { color: #FF0000 } /* Generic.Error */
+.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.highlight .gi { color: #00A000 } /* Generic.Inserted */
+.highlight .go { color: #333333 } /* Generic.Output */
+.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
+.highlight .gs { font-weight: bold } /* Generic.Strong */
+.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.highlight .gt { color: #0044DD } /* Generic.Traceback */
+.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
+.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
+.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
+.highlight .kp { color: #007020 } /* Keyword.Pseudo */
+.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
+.highlight .kt { color: #902000 } /* Keyword.Type */
+.highlight .m { color: #208050 } /* Literal.Number */
+.highlight .s { color: #4070a0 } /* Literal.String */
+.highlight .na { color: #4070a0 } /* Name.Attribute */
+.highlight .nb { color: #007020 } /* Name.Builtin */
+.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
+.highlight .no { color: #60add5 } /* Name.Constant */
+.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
+.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
+.highlight .ne { color: #007020 } /* Name.Exception */
+.highlight .nf { color: #06287e } /* Name.Function */
+.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
+.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
+.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
+.highlight .nv { color: #bb60d5 } /* Name.Variable */
+.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
+.highlight .w { color: #bbbbbb } /* Text.Whitespace */
+.highlight .mb { color: #208050 } /* Literal.Number.Bin */
+.highlight .mf { color: #208050 } /* Literal.Number.Float */
+.highlight .mh { color: #208050 } /* Literal.Number.Hex */
+.highlight .mi { color: #208050 } /* Literal.Number.Integer */
+.highlight .mo { color: #208050 } /* Literal.Number.Oct */
+.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
+.highlight .sc { color: #4070a0 } /* Literal.String.Char */
+.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
+.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
+.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
+.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
+.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
+.highlight .sx { color: #c65d09 } /* Literal.String.Other */
+.highlight .sr { color: #235388 } /* Literal.String.Regex */
+.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
+.highlight .ss { color: #517918 } /* Literal.String.Symbol */
+.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
+.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
+.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
+.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
+.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
\ No newline at end of file
diff --git a/docs/build/html/_static/searchtools.js b/docs/build/html/_static/searchtools.js
new file mode 100644
index 0000000..066857c
--- /dev/null
+++ b/docs/build/html/_static/searchtools.js
@@ -0,0 +1,651 @@
+/*
+ * searchtools.js_t
+ * ~~~~~~~~~~~~~~~~
+ *
+ * Sphinx JavaScript utilities for the full-text search.
+ *
+ * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+
+/* Non-minified version JS is _stemmer.js if file is provided */
+/**
+ * Porter Stemmer
+ */
+var Stemmer = function() {
+
+ var step2list = {
+ ational: 'ate',
+ tional: 'tion',
+ enci: 'ence',
+ anci: 'ance',
+ izer: 'ize',
+ bli: 'ble',
+ alli: 'al',
+ entli: 'ent',
+ eli: 'e',
+ ousli: 'ous',
+ ization: 'ize',
+ ation: 'ate',
+ ator: 'ate',
+ alism: 'al',
+ iveness: 'ive',
+ fulness: 'ful',
+ ousness: 'ous',
+ aliti: 'al',
+ iviti: 'ive',
+ biliti: 'ble',
+ logi: 'log'
+ };
+
+ var step3list = {
+ icate: 'ic',
+ ative: '',
+ alize: 'al',
+ iciti: 'ic',
+ ical: 'ic',
+ ful: '',
+ ness: ''
+ };
+
+ var c = "[^aeiou]"; // consonant
+ var v = "[aeiouy]"; // vowel
+ var C = c + "[^aeiouy]*"; // consonant sequence
+ var V = v + "[aeiou]*"; // vowel sequence
+
+ var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
+ var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
+ var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
+ var s_v = "^(" + C + ")?" + v; // vowel in stem
+
+ this.stemWord = function (w) {
+ var stem;
+ var suffix;
+ var firstch;
+ var origword = w;
+
+ if (w.length < 3)
+ return w;
+
+ var re;
+ var re2;
+ var re3;
+ var re4;
+
+ firstch = w.substr(0,1);
+ if (firstch == "y")
+ w = firstch.toUpperCase() + w.substr(1);
+
+ // Step 1a
+ re = /^(.+?)(ss|i)es$/;
+ re2 = /^(.+?)([^s])s$/;
+
+ if (re.test(w))
+ w = w.replace(re,"$1$2");
+ else if (re2.test(w))
+ w = w.replace(re2,"$1$2");
+
+ // Step 1b
+ re = /^(.+?)eed$/;
+ re2 = /^(.+?)(ed|ing)$/;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ re = new RegExp(mgr0);
+ if (re.test(fp[1])) {
+ re = /.$/;
+ w = w.replace(re,"");
+ }
+ }
+ else if (re2.test(w)) {
+ var fp = re2.exec(w);
+ stem = fp[1];
+ re2 = new RegExp(s_v);
+ if (re2.test(stem)) {
+ w = stem;
+ re2 = /(at|bl|iz)$/;
+ re3 = new RegExp("([^aeiouylsz])\\1$");
+ re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
+ if (re2.test(w))
+ w = w + "e";
+ else if (re3.test(w)) {
+ re = /.$/;
+ w = w.replace(re,"");
+ }
+ else if (re4.test(w))
+ w = w + "e";
+ }
+ }
+
+ // Step 1c
+ re = /^(.+?)y$/;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ stem = fp[1];
+ re = new RegExp(s_v);
+ if (re.test(stem))
+ w = stem + "i";
+ }
+
+ // Step 2
+ re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ stem = fp[1];
+ suffix = fp[2];
+ re = new RegExp(mgr0);
+ if (re.test(stem))
+ w = stem + step2list[suffix];
+ }
+
+ // Step 3
+ re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ stem = fp[1];
+ suffix = fp[2];
+ re = new RegExp(mgr0);
+ if (re.test(stem))
+ w = stem + step3list[suffix];
+ }
+
+ // Step 4
+ re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
+ re2 = /^(.+?)(s|t)(ion)$/;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ stem = fp[1];
+ re = new RegExp(mgr1);
+ if (re.test(stem))
+ w = stem;
+ }
+ else if (re2.test(w)) {
+ var fp = re2.exec(w);
+ stem = fp[1] + fp[2];
+ re2 = new RegExp(mgr1);
+ if (re2.test(stem))
+ w = stem;
+ }
+
+ // Step 5
+ re = /^(.+?)e$/;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ stem = fp[1];
+ re = new RegExp(mgr1);
+ re2 = new RegExp(meq1);
+ re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
+ if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
+ w = stem;
+ }
+ re = /ll$/;
+ re2 = new RegExp(mgr1);
+ if (re.test(w) && re2.test(w)) {
+ re = /.$/;
+ w = w.replace(re,"");
+ }
+
+ // and turn initial Y back to y
+ if (firstch == "y")
+ w = firstch.toLowerCase() + w.substr(1);
+ return w;
+ }
+}
+
+
+
+/**
+ * Simple result scoring code.
+ */
+var Scorer = {
+ // Implement the following function to further tweak the score for each result
+ // The function takes a result array [filename, title, anchor, descr, score]
+ // and returns the new score.
+ /*
+ score: function(result) {
+ return result[4];
+ },
+ */
+
+ // query matches the full name of an object
+ objNameMatch: 11,
+ // or matches in the last dotted part of the object name
+ objPartialMatch: 6,
+ // Additive scores depending on the priority of the object
+ objPrio: {0: 15, // used to be importantResults
+ 1: 5, // used to be objectResults
+ 2: -5}, // used to be unimportantResults
+ // Used when the priority is not in the mapping.
+ objPrioDefault: 0,
+
+ // query found in title
+ title: 15,
+ // query found in terms
+ term: 5
+};
+
+
+/**
+ * Search Module
+ */
+var Search = {
+
+ _index : null,
+ _queued_query : null,
+ _pulse_status : -1,
+
+ init : function() {
+ var params = $.getQueryParameters();
+ if (params.q) {
+ var query = params.q[0];
+ $('input[name="q"]')[0].value = query;
+ this.performSearch(query);
+ }
+ },
+
+ loadIndex : function(url) {
+ $.ajax({type: "GET", url: url, data: null,
+ dataType: "script", cache: true,
+ complete: function(jqxhr, textstatus) {
+ if (textstatus != "success") {
+ document.getElementById("searchindexloader").src = url;
+ }
+ }});
+ },
+
+ setIndex : function(index) {
+ var q;
+ this._index = index;
+ if ((q = this._queued_query) !== null) {
+ this._queued_query = null;
+ Search.query(q);
+ }
+ },
+
+ hasIndex : function() {
+ return this._index !== null;
+ },
+
+ deferQuery : function(query) {
+ this._queued_query = query;
+ },
+
+ stopPulse : function() {
+ this._pulse_status = 0;
+ },
+
+ startPulse : function() {
+ if (this._pulse_status >= 0)
+ return;
+ function pulse() {
+ var i;
+ Search._pulse_status = (Search._pulse_status + 1) % 4;
+ var dotString = '';
+ for (i = 0; i < Search._pulse_status; i++)
+ dotString += '.';
+ Search.dots.text(dotString);
+ if (Search._pulse_status > -1)
+ window.setTimeout(pulse, 500);
+ }
+ pulse();
+ },
+
+ /**
+ * perform a search for something (or wait until index is loaded)
+ */
+ performSearch : function(query) {
+ // create the required interface elements
+ this.out = $('#search-results');
+ this.title = $('
' + _('Searching') + ' ').appendTo(this.out);
+ this.dots = $('
').appendTo(this.title);
+ this.status = $('
').appendTo(this.out);
+ this.output = $('
').appendTo(this.out);
+
+ $('#search-progress').text(_('Preparing search...'));
+ this.startPulse();
+
+ // index already loaded, the browser was quick!
+ if (this.hasIndex())
+ this.query(query);
+ else
+ this.deferQuery(query);
+ },
+
+ /**
+ * execute search (requires search index to be loaded)
+ */
+ query : function(query) {
+ var i;
+ var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"];
+
+ // stem the searchterms and add them to the correct list
+ var stemmer = new Stemmer();
+ var searchterms = [];
+ var excluded = [];
+ var hlterms = [];
+ var tmp = query.split(/\s+/);
+ var objectterms = [];
+ for (i = 0; i < tmp.length; i++) {
+ if (tmp[i] !== "") {
+ objectterms.push(tmp[i].toLowerCase());
+ }
+
+ if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i].match(/^\d+$/) ||
+ tmp[i] === "") {
+ // skip this "word"
+ continue;
+ }
+ // stem the word
+ var word = stemmer.stemWord(tmp[i].toLowerCase());
+ var toAppend;
+ // select the correct list
+ if (word[0] == '-') {
+ toAppend = excluded;
+ word = word.substr(1);
+ }
+ else {
+ toAppend = searchterms;
+ hlterms.push(tmp[i].toLowerCase());
+ }
+ // only add if not already in the list
+ if (!$u.contains(toAppend, word))
+ toAppend.push(word);
+ }
+ var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
+
+ // console.debug('SEARCH: searching for:');
+ // console.info('required: ', searchterms);
+ // console.info('excluded: ', excluded);
+
+ // prepare search
+ var terms = this._index.terms;
+ var titleterms = this._index.titleterms;
+
+ // array of [filename, title, anchor, descr, score]
+ var results = [];
+ $('#search-progress').empty();
+
+ // lookup as object
+ for (i = 0; i < objectterms.length; i++) {
+ var others = [].concat(objectterms.slice(0, i),
+ objectterms.slice(i+1, objectterms.length));
+ results = results.concat(this.performObjectSearch(objectterms[i], others));
+ }
+
+ // lookup as search terms in fulltext
+ results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms));
+
+ // let the scorer override scores with a custom scoring function
+ if (Scorer.score) {
+ for (i = 0; i < results.length; i++)
+ results[i][4] = Scorer.score(results[i]);
+ }
+
+ // now sort the results by score (in opposite order of appearance, since the
+ // display function below uses pop() to retrieve items) and then
+ // alphabetically
+ results.sort(function(a, b) {
+ var left = a[4];
+ var right = b[4];
+ if (left > right) {
+ return 1;
+ } else if (left < right) {
+ return -1;
+ } else {
+ // same score: sort alphabetically
+ left = a[1].toLowerCase();
+ right = b[1].toLowerCase();
+ return (left > right) ? -1 : ((left < right) ? 1 : 0);
+ }
+ });
+
+ // for debugging
+ //Search.lastresults = results.slice(); // a copy
+ //console.info('search results:', Search.lastresults);
+
+ // print the results
+ var resultCount = results.length;
+ function displayNextItem() {
+ // results left, load the summary and display it
+ if (results.length) {
+ var item = results.pop();
+ var listItem = $('
');
+ if (DOCUMENTATION_OPTIONS.FILE_SUFFIX === '') {
+ // dirhtml builder
+ var dirname = item[0] + '/';
+ if (dirname.match(/\/index\/$/)) {
+ dirname = dirname.substring(0, dirname.length-6);
+ } else if (dirname == 'index/') {
+ dirname = '';
+ }
+ listItem.append($('
').attr('href',
+ DOCUMENTATION_OPTIONS.URL_ROOT + dirname +
+ highlightstring + item[2]).html(item[1]));
+ } else {
+ // normal html builders
+ listItem.append($('
').attr('href',
+ item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
+ highlightstring + item[2]).html(item[1]));
+ }
+ if (item[3]) {
+ listItem.append($('
(' + item[3] + ') '));
+ Search.output.append(listItem);
+ listItem.slideDown(5, function() {
+ displayNextItem();
+ });
+ } else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
+ $.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[0] + '.txt',
+ dataType: "text",
+ complete: function(jqxhr, textstatus) {
+ var data = jqxhr.responseText;
+ if (data !== '' && data !== undefined) {
+ listItem.append(Search.makeSearchSummary(data, searchterms, hlterms));
+ }
+ Search.output.append(listItem);
+ listItem.slideDown(5, function() {
+ displayNextItem();
+ });
+ }});
+ } else {
+ // no source available, just display title
+ Search.output.append(listItem);
+ listItem.slideDown(5, function() {
+ displayNextItem();
+ });
+ }
+ }
+ // search finished, update title and status message
+ else {
+ Search.stopPulse();
+ Search.title.text(_('Search Results'));
+ if (!resultCount)
+ Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
+ else
+ Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
+ Search.status.fadeIn(500);
+ }
+ }
+ displayNextItem();
+ },
+
+ /**
+ * search for object names
+ */
+ performObjectSearch : function(object, otherterms) {
+ var filenames = this._index.filenames;
+ var objects = this._index.objects;
+ var objnames = this._index.objnames;
+ var titles = this._index.titles;
+
+ var i;
+ var results = [];
+
+ for (var prefix in objects) {
+ for (var name in objects[prefix]) {
+ var fullname = (prefix ? prefix + '.' : '') + name;
+ if (fullname.toLowerCase().indexOf(object) > -1) {
+ var score = 0;
+ var parts = fullname.split('.');
+ // check for different match types: exact matches of full name or
+ // "last name" (i.e. last dotted part)
+ if (fullname == object || parts[parts.length - 1] == object) {
+ score += Scorer.objNameMatch;
+ // matches in last name
+ } else if (parts[parts.length - 1].indexOf(object) > -1) {
+ score += Scorer.objPartialMatch;
+ }
+ var match = objects[prefix][name];
+ var objname = objnames[match[1]][2];
+ var title = titles[match[0]];
+ // If more than one term searched for, we require other words to be
+ // found in the name/title/description
+ if (otherterms.length > 0) {
+ var haystack = (prefix + ' ' + name + ' ' +
+ objname + ' ' + title).toLowerCase();
+ var allfound = true;
+ for (i = 0; i < otherterms.length; i++) {
+ if (haystack.indexOf(otherterms[i]) == -1) {
+ allfound = false;
+ break;
+ }
+ }
+ if (!allfound) {
+ continue;
+ }
+ }
+ var descr = objname + _(', in ') + title;
+
+ var anchor = match[3];
+ if (anchor === '')
+ anchor = fullname;
+ else if (anchor == '-')
+ anchor = objnames[match[1]][1] + '-' + fullname;
+ // add custom score for some objects according to scorer
+ if (Scorer.objPrio.hasOwnProperty(match[2])) {
+ score += Scorer.objPrio[match[2]];
+ } else {
+ score += Scorer.objPrioDefault;
+ }
+ results.push([filenames[match[0]], fullname, '#'+anchor, descr, score]);
+ }
+ }
+ }
+
+ return results;
+ },
+
+ /**
+ * search for full-text terms in the index
+ */
+ performTermsSearch : function(searchterms, excluded, terms, titleterms) {
+ var filenames = this._index.filenames;
+ var titles = this._index.titles;
+
+ var i, j, file;
+ var fileMap = {};
+ var scoreMap = {};
+ var results = [];
+
+ // perform the search on the required terms
+ for (i = 0; i < searchterms.length; i++) {
+ var word = searchterms[i];
+ var files = [];
+ var _o = [
+ {files: terms[word], score: Scorer.term},
+ {files: titleterms[word], score: Scorer.title}
+ ];
+
+ // no match but word was a required one
+ if ($u.every(_o, function(o){return o.files === undefined;})) {
+ break;
+ }
+ // found search word in contents
+ $u.each(_o, function(o) {
+ var _files = o.files;
+ if (_files === undefined)
+ return
+
+ if (_files.length === undefined)
+ _files = [_files];
+ files = files.concat(_files);
+
+ // set score for the word in each file to Scorer.term
+ for (j = 0; j < _files.length; j++) {
+ file = _files[j];
+ if (!(file in scoreMap))
+ scoreMap[file] = {}
+ scoreMap[file][word] = o.score;
+ }
+ });
+
+ // create the mapping
+ for (j = 0; j < files.length; j++) {
+ file = files[j];
+ if (file in fileMap)
+ fileMap[file].push(word);
+ else
+ fileMap[file] = [word];
+ }
+ }
+
+ // now check if the files don't contain excluded terms
+ for (file in fileMap) {
+ var valid = true;
+
+ // check if all requirements are matched
+ if (fileMap[file].length != searchterms.length)
+ continue;
+
+ // ensure that none of the excluded terms is in the search result
+ for (i = 0; i < excluded.length; i++) {
+ if (terms[excluded[i]] == file ||
+ titleterms[excluded[i]] == file ||
+ $u.contains(terms[excluded[i]] || [], file) ||
+ $u.contains(titleterms[excluded[i]] || [], file)) {
+ valid = false;
+ break;
+ }
+ }
+
+ // if we have still a valid result we can add it to the result list
+ if (valid) {
+ // select one (max) score for the file.
+ // for better ranking, we should calculate ranking by using words statistics like basic tf-idf...
+ var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]}));
+ results.push([filenames[file], titles[file], '', null, score]);
+ }
+ }
+ return results;
+ },
+
+ /**
+ * helper function to return a node containing the
+ * search summary for a given text. keywords is a list
+ * of stemmed words, hlwords is the list of normal, unstemmed
+ * words. the first one is used to find the occurrence, the
+ * latter for highlighting it.
+ */
+ makeSearchSummary : function(text, keywords, hlwords) {
+ var textLower = text.toLowerCase();
+ var start = 0;
+ $.each(keywords, function() {
+ var i = textLower.indexOf(this.toLowerCase());
+ if (i > -1)
+ start = i;
+ });
+ start = Math.max(start - 120, 0);
+ var excerpt = ((start > 0) ? '...' : '') +
+ $.trim(text.substr(start, 240)) +
+ ((start + 240 - text.length) ? '...' : '');
+ var rv = $('
').text(excerpt);
+ $.each(hlwords, function() {
+ rv = rv.highlightText(this, 'highlighted');
+ });
+ return rv;
+ }
+};
+
+$(document).ready(function() {
+ Search.init();
+});
\ No newline at end of file
diff --git a/docs/build/html/_static/sidebar.js b/docs/build/html/_static/sidebar.js
new file mode 100644
index 0000000..4282fe9
--- /dev/null
+++ b/docs/build/html/_static/sidebar.js
@@ -0,0 +1,159 @@
+/*
+ * sidebar.js
+ * ~~~~~~~~~~
+ *
+ * This script makes the Sphinx sidebar collapsible.
+ *
+ * .sphinxsidebar contains .sphinxsidebarwrapper. This script adds
+ * in .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton
+ * used to collapse and expand the sidebar.
+ *
+ * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden
+ * and the width of the sidebar and the margin-left of the document
+ * are decreased. When the sidebar is expanded the opposite happens.
+ * This script saves a per-browser/per-session cookie used to
+ * remember the position of the sidebar among the pages.
+ * Once the browser is closed the cookie is deleted and the position
+ * reset to the default (expanded).
+ *
+ * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+$(function() {
+
+
+
+
+
+
+
+
+ // global elements used by the functions.
+ // the 'sidebarbutton' element is defined as global after its
+ // creation, in the add_sidebar_button function
+ var bodywrapper = $('.bodywrapper');
+ var sidebar = $('.sphinxsidebar');
+ var sidebarwrapper = $('.sphinxsidebarwrapper');
+
+ // for some reason, the document has no sidebar; do not run into errors
+ if (!sidebar.length) return;
+
+ // original margin-left of the bodywrapper and width of the sidebar
+ // with the sidebar expanded
+ var bw_margin_expanded = bodywrapper.css('margin-left');
+ var ssb_width_expanded = sidebar.width();
+
+ // margin-left of the bodywrapper and width of the sidebar
+ // with the sidebar collapsed
+ var bw_margin_collapsed = '.8em';
+ var ssb_width_collapsed = '.8em';
+
+ // colors used by the current theme
+ var dark_color = $('.related').css('background-color');
+ var light_color = $('.document').css('background-color');
+
+ function sidebar_is_collapsed() {
+ return sidebarwrapper.is(':not(:visible)');
+ }
+
+ function toggle_sidebar() {
+ if (sidebar_is_collapsed())
+ expand_sidebar();
+ else
+ collapse_sidebar();
+ }
+
+ function collapse_sidebar() {
+ sidebarwrapper.hide();
+ sidebar.css('width', ssb_width_collapsed);
+ bodywrapper.css('margin-left', bw_margin_collapsed);
+ sidebarbutton.css({
+ 'margin-left': '0',
+ 'height': bodywrapper.height()
+ });
+ sidebarbutton.find('span').text('»');
+ sidebarbutton.attr('title', _('Expand sidebar'));
+ document.cookie = 'sidebar=collapsed';
+ }
+
+ function expand_sidebar() {
+ bodywrapper.css('margin-left', bw_margin_expanded);
+ sidebar.css('width', ssb_width_expanded);
+ sidebarwrapper.show();
+ sidebarbutton.css({
+ 'margin-left': ssb_width_expanded-12,
+ 'height': bodywrapper.height()
+ });
+ sidebarbutton.find('span').text('«');
+ sidebarbutton.attr('title', _('Collapse sidebar'));
+ document.cookie = 'sidebar=expanded';
+ }
+
+ function add_sidebar_button() {
+ sidebarwrapper.css({
+ 'float': 'left',
+ 'margin-right': '0',
+ 'width': ssb_width_expanded - 28
+ });
+ // create the button
+ sidebar.append(
+ ''
+ );
+ var sidebarbutton = $('#sidebarbutton');
+ light_color = sidebarbutton.css('background-color');
+ // find the height of the viewport to center the '<<' in the page
+ var viewport_height;
+ if (window.innerHeight)
+ viewport_height = window.innerHeight;
+ else
+ viewport_height = $(window).height();
+ sidebarbutton.find('span').css({
+ 'display': 'block',
+ 'margin-top': (viewport_height - sidebar.position().top - 20) / 2
+ });
+
+ sidebarbutton.click(toggle_sidebar);
+ sidebarbutton.attr('title', _('Collapse sidebar'));
+ sidebarbutton.css({
+ 'color': '#FFFFFF',
+ 'border-left': '1px solid ' + dark_color,
+ 'font-size': '1.2em',
+ 'cursor': 'pointer',
+ 'height': bodywrapper.height(),
+ 'padding-top': '1px',
+ 'margin-left': ssb_width_expanded - 12
+ });
+
+ sidebarbutton.hover(
+ function () {
+ $(this).css('background-color', dark_color);
+ },
+ function () {
+ $(this).css('background-color', light_color);
+ }
+ );
+ }
+
+ function set_position_from_cookie() {
+ if (!document.cookie)
+ return;
+ var items = document.cookie.split(';');
+ for(var k=0; k
2;
+ if (obj == null) obj = [];
+ if (nativeReduce && obj.reduce === nativeReduce) {
+ if (context) iterator = _.bind(iterator, context);
+ return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
+ }
+ each(obj, function(value, index, list) {
+ if (!initial) {
+ memo = value;
+ initial = true;
+ } else {
+ memo = iterator.call(context, memo, value, index, list);
+ }
+ });
+ if (!initial) throw new TypeError('Reduce of empty array with no initial value');
+ return memo;
+ };
+
+ // The right-associative version of reduce, also known as `foldr`.
+ // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
+ _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
+ var initial = arguments.length > 2;
+ if (obj == null) obj = [];
+ if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
+ if (context) iterator = _.bind(iterator, context);
+ return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
+ }
+ var reversed = _.toArray(obj).reverse();
+ if (context && !initial) iterator = _.bind(iterator, context);
+ return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
+ };
+
+ // Return the first value which passes a truth test. Aliased as `detect`.
+ _.find = _.detect = function(obj, iterator, context) {
+ var result;
+ any(obj, function(value, index, list) {
+ if (iterator.call(context, value, index, list)) {
+ result = value;
+ return true;
+ }
+ });
+ return result;
+ };
+
+ // Return all the elements that pass a truth test.
+ // Delegates to **ECMAScript 5**'s native `filter` if available.
+ // Aliased as `select`.
+ _.filter = _.select = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) return results;
+ if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
+ each(obj, function(value, index, list) {
+ if (iterator.call(context, value, index, list)) results[results.length] = value;
+ });
+ return results;
+ };
+
+ // Return all the elements for which a truth test fails.
+ _.reject = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) return results;
+ each(obj, function(value, index, list) {
+ if (!iterator.call(context, value, index, list)) results[results.length] = value;
+ });
+ return results;
+ };
+
+ // Determine whether all of the elements match a truth test.
+ // Delegates to **ECMAScript 5**'s native `every` if available.
+ // Aliased as `all`.
+ _.every = _.all = function(obj, iterator, context) {
+ var result = true;
+ if (obj == null) return result;
+ if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
+ each(obj, function(value, index, list) {
+ if (!(result = result && iterator.call(context, value, index, list))) return breaker;
+ });
+ return result;
+ };
+
+ // Determine if at least one element in the object matches a truth test.
+ // Delegates to **ECMAScript 5**'s native `some` if available.
+ // Aliased as `any`.
+ var any = _.some = _.any = function(obj, iterator, context) {
+ iterator || (iterator = _.identity);
+ var result = false;
+ if (obj == null) return result;
+ if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
+ each(obj, function(value, index, list) {
+ if (result || (result = iterator.call(context, value, index, list))) return breaker;
+ });
+ return !!result;
+ };
+
+ // Determine if a given value is included in the array or object using `===`.
+ // Aliased as `contains`.
+ _.include = _.contains = function(obj, target) {
+ var found = false;
+ if (obj == null) return found;
+ if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
+ found = any(obj, function(value) {
+ return value === target;
+ });
+ return found;
+ };
+
+ // Invoke a method (with arguments) on every item in a collection.
+ _.invoke = function(obj, method) {
+ var args = slice.call(arguments, 2);
+ return _.map(obj, function(value) {
+ return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
+ });
+ };
+
+ // Convenience version of a common use case of `map`: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, function(value){ return value[key]; });
+ };
+
+ // Return the maximum element or (element-based computation).
+ _.max = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
+ if (!iterator && _.isEmpty(obj)) return -Infinity;
+ var result = {computed : -Infinity};
+ each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed >= result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ // Return the minimum element (or element-based computation).
+ _.min = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
+ if (!iterator && _.isEmpty(obj)) return Infinity;
+ var result = {computed : Infinity};
+ each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed < result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ // Shuffle an array.
+ _.shuffle = function(obj) {
+ var shuffled = [], rand;
+ each(obj, function(value, index, list) {
+ if (index == 0) {
+ shuffled[0] = value;
+ } else {
+ rand = Math.floor(Math.random() * (index + 1));
+ shuffled[index] = shuffled[rand];
+ shuffled[rand] = value;
+ }
+ });
+ return shuffled;
+ };
+
+ // Sort the object's values by a criterion produced by an iterator.
+ _.sortBy = function(obj, iterator, context) {
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value : value,
+ criteria : iterator.call(context, value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }), 'value');
+ };
+
+ // Groups the object's values by a criterion. Pass either a string attribute
+ // to group by, or a function that returns the criterion.
+ _.groupBy = function(obj, val) {
+ var result = {};
+ var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
+ each(obj, function(value, index) {
+ var key = iterator(value, index);
+ (result[key] || (result[key] = [])).push(value);
+ });
+ return result;
+ };
+
+ // Use a comparator function to figure out at what index an object should
+ // be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iterator) {
+ iterator || (iterator = _.identity);
+ var low = 0, high = array.length;
+ while (low < high) {
+ var mid = (low + high) >> 1;
+ iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
+ }
+ return low;
+ };
+
+ // Safely convert anything iterable into a real, live array.
+ _.toArray = function(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ if (_.isArray(iterable)) return slice.call(iterable);
+ if (_.isArguments(iterable)) return slice.call(iterable);
+ return _.values(iterable);
+ };
+
+ // Return the number of elements in an object.
+ _.size = function(obj) {
+ return _.toArray(obj).length;
+ };
+
+ // Array Functions
+ // ---------------
+
+ // Get the first element of an array. Passing **n** will return the first N
+ // values in the array. Aliased as `head`. The **guard** check allows it to work
+ // with `_.map`.
+ _.first = _.head = function(array, n, guard) {
+ return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
+ };
+
+ // Returns everything but the last entry of the array. Especcialy useful on
+ // the arguments object. Passing **n** will return all the values in
+ // the array, excluding the last N. The **guard** check allows it to work with
+ // `_.map`.
+ _.initial = function(array, n, guard) {
+ return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
+ };
+
+ // Get the last element of an array. Passing **n** will return the last N
+ // values in the array. The **guard** check allows it to work with `_.map`.
+ _.last = function(array, n, guard) {
+ if ((n != null) && !guard) {
+ return slice.call(array, Math.max(array.length - n, 0));
+ } else {
+ return array[array.length - 1];
+ }
+ };
+
+ // Returns everything but the first entry of the array. Aliased as `tail`.
+ // Especially useful on the arguments object. Passing an **index** will return
+ // the rest of the values in the array from that index onward. The **guard**
+ // check allows it to work with `_.map`.
+ _.rest = _.tail = function(array, index, guard) {
+ return slice.call(array, (index == null) || guard ? 1 : index);
+ };
+
+ // Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.filter(array, function(value){ return !!value; });
+ };
+
+ // Return a completely flattened version of an array.
+ _.flatten = function(array, shallow) {
+ return _.reduce(array, function(memo, value) {
+ if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
+ memo[memo.length] = value;
+ return memo;
+ }, []);
+ };
+
+ // Return a version of the array that does not contain the specified value(s).
+ _.without = function(array) {
+ return _.difference(array, slice.call(arguments, 1));
+ };
+
+ // Produce a duplicate-free version of the array. If the array has already
+ // been sorted, you have the option of using a faster algorithm.
+ // Aliased as `unique`.
+ _.uniq = _.unique = function(array, isSorted, iterator) {
+ var initial = iterator ? _.map(array, iterator) : array;
+ var result = [];
+ _.reduce(initial, function(memo, el, i) {
+ if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) {
+ memo[memo.length] = el;
+ result[result.length] = array[i];
+ }
+ return memo;
+ }, []);
+ return result;
+ };
+
+ // Produce an array that contains the union: each distinct element from all of
+ // the passed-in arrays.
+ _.union = function() {
+ return _.uniq(_.flatten(arguments, true));
+ };
+
+ // Produce an array that contains every item shared between all the
+ // passed-in arrays. (Aliased as "intersect" for back-compat.)
+ _.intersection = _.intersect = function(array) {
+ var rest = slice.call(arguments, 1);
+ return _.filter(_.uniq(array), function(item) {
+ return _.every(rest, function(other) {
+ return _.indexOf(other, item) >= 0;
+ });
+ });
+ };
+
+ // Take the difference between one array and a number of other arrays.
+ // Only the elements present in just the first array will remain.
+ _.difference = function(array) {
+ var rest = _.flatten(slice.call(arguments, 1));
+ return _.filter(array, function(value){ return !_.include(rest, value); });
+ };
+
+ // Zip together multiple lists into a single array -- elements that share
+ // an index go together.
+ _.zip = function() {
+ var args = slice.call(arguments);
+ var length = _.max(_.pluck(args, 'length'));
+ var results = new Array(length);
+ for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
+ return results;
+ };
+
+ // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
+ // we need this function. Return the position of the first occurrence of an
+ // item in an array, or -1 if the item is not included in the array.
+ // Delegates to **ECMAScript 5**'s native `indexOf` if available.
+ // If the array is large and already in sort order, pass `true`
+ // for **isSorted** to use binary search.
+ _.indexOf = function(array, item, isSorted) {
+ if (array == null) return -1;
+ var i, l;
+ if (isSorted) {
+ i = _.sortedIndex(array, item);
+ return array[i] === item ? i : -1;
+ }
+ if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
+ for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
+ return -1;
+ };
+
+ // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
+ _.lastIndexOf = function(array, item) {
+ if (array == null) return -1;
+ if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
+ var i = array.length;
+ while (i--) if (i in array && array[i] === item) return i;
+ return -1;
+ };
+
+ // Generate an integer Array containing an arithmetic progression. A port of
+ // the native Python `range()` function. See
+ // [the Python documentation](http://docs.python.org/library/functions.html#range).
+ _.range = function(start, stop, step) {
+ if (arguments.length <= 1) {
+ stop = start || 0;
+ start = 0;
+ }
+ step = arguments[2] || 1;
+
+ var len = Math.max(Math.ceil((stop - start) / step), 0);
+ var idx = 0;
+ var range = new Array(len);
+
+ while(idx < len) {
+ range[idx++] = start;
+ start += step;
+ }
+
+ return range;
+ };
+
+ // Function (ahem) Functions
+ // ------------------
+
+ // Reusable constructor function for prototype setting.
+ var ctor = function(){};
+
+ // Create a function bound to a given object (assigning `this`, and arguments,
+ // optionally). Binding with arguments is also known as `curry`.
+ // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
+ // We check for `func.bind` first, to fail fast when `func` is undefined.
+ _.bind = function bind(func, context) {
+ var bound, args;
+ if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+ if (!_.isFunction(func)) throw new TypeError;
+ args = slice.call(arguments, 2);
+ return bound = function() {
+ if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
+ ctor.prototype = func.prototype;
+ var self = new ctor;
+ var result = func.apply(self, args.concat(slice.call(arguments)));
+ if (Object(result) === result) return result;
+ return self;
+ };
+ };
+
+ // Bind all of an object's methods to that object. Useful for ensuring that
+ // all callbacks defined on an object belong to it.
+ _.bindAll = function(obj) {
+ var funcs = slice.call(arguments, 1);
+ if (funcs.length == 0) funcs = _.functions(obj);
+ each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
+ return obj;
+ };
+
+ // Memoize an expensive function by storing its results.
+ _.memoize = function(func, hasher) {
+ var memo = {};
+ hasher || (hasher = _.identity);
+ return function() {
+ var key = hasher.apply(this, arguments);
+ return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
+ };
+ };
+
+ // Delays a function for the given number of milliseconds, and then calls
+ // it with the arguments supplied.
+ _.delay = function(func, wait) {
+ var args = slice.call(arguments, 2);
+ return setTimeout(function(){ return func.apply(func, args); }, wait);
+ };
+
+ // Defers a function, scheduling it to run after the current call stack has
+ // cleared.
+ _.defer = function(func) {
+ return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
+ };
+
+ // Returns a function, that, when invoked, will only be triggered at most once
+ // during a given window of time.
+ _.throttle = function(func, wait) {
+ var context, args, timeout, throttling, more;
+ var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
+ return function() {
+ context = this; args = arguments;
+ var later = function() {
+ timeout = null;
+ if (more) func.apply(context, args);
+ whenDone();
+ };
+ if (!timeout) timeout = setTimeout(later, wait);
+ if (throttling) {
+ more = true;
+ } else {
+ func.apply(context, args);
+ }
+ whenDone();
+ throttling = true;
+ };
+ };
+
+ // Returns a function, that, as long as it continues to be invoked, will not
+ // be triggered. The function will be called after it stops being called for
+ // N milliseconds.
+ _.debounce = function(func, wait) {
+ var timeout;
+ return function() {
+ var context = this, args = arguments;
+ var later = function() {
+ timeout = null;
+ func.apply(context, args);
+ };
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ };
+ };
+
+ // Returns a function that will be executed at most one time, no matter how
+ // often you call it. Useful for lazy initialization.
+ _.once = function(func) {
+ var ran = false, memo;
+ return function() {
+ if (ran) return memo;
+ ran = true;
+ return memo = func.apply(this, arguments);
+ };
+ };
+
+ // Returns the first function passed as an argument to the second,
+ // allowing you to adjust arguments, run code before and after, and
+ // conditionally execute the original function.
+ _.wrap = function(func, wrapper) {
+ return function() {
+ var args = [func].concat(slice.call(arguments, 0));
+ return wrapper.apply(this, args);
+ };
+ };
+
+ // Returns a function that is the composition of a list of functions, each
+ // consuming the return value of the function that follows.
+ _.compose = function() {
+ var funcs = arguments;
+ return function() {
+ var args = arguments;
+ for (var i = funcs.length - 1; i >= 0; i--) {
+ args = [funcs[i].apply(this, args)];
+ }
+ return args[0];
+ };
+ };
+
+ // Returns a function that will only be executed after being called N times.
+ _.after = function(times, func) {
+ if (times <= 0) return func();
+ return function() {
+ if (--times < 1) { return func.apply(this, arguments); }
+ };
+ };
+
+ // Object Functions
+ // ----------------
+
+ // Retrieve the names of an object's properties.
+ // Delegates to **ECMAScript 5**'s native `Object.keys`
+ _.keys = nativeKeys || function(obj) {
+ if (obj !== Object(obj)) throw new TypeError('Invalid object');
+ var keys = [];
+ for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
+ return keys;
+ };
+
+ // Retrieve the values of an object's properties.
+ _.values = function(obj) {
+ return _.map(obj, _.identity);
+ };
+
+ // Return a sorted list of the function names available on the object.
+ // Aliased as `methods`
+ _.functions = _.methods = function(obj) {
+ var names = [];
+ for (var key in obj) {
+ if (_.isFunction(obj[key])) names.push(key);
+ }
+ return names.sort();
+ };
+
+ // Extend a given object with all the properties in passed-in object(s).
+ _.extend = function(obj) {
+ each(slice.call(arguments, 1), function(source) {
+ for (var prop in source) {
+ obj[prop] = source[prop];
+ }
+ });
+ return obj;
+ };
+
+ // Fill in a given object with default properties.
+ _.defaults = function(obj) {
+ each(slice.call(arguments, 1), function(source) {
+ for (var prop in source) {
+ if (obj[prop] == null) obj[prop] = source[prop];
+ }
+ });
+ return obj;
+ };
+
+ // Create a (shallow-cloned) duplicate of an object.
+ _.clone = function(obj) {
+ if (!_.isObject(obj)) return obj;
+ return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+ };
+
+ // Invokes interceptor with the obj, and then returns obj.
+ // The primary purpose of this method is to "tap into" a method chain, in
+ // order to perform operations on intermediate results within the chain.
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ };
+
+ // Internal recursive comparison function.
+ function eq(a, b, stack) {
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
+ // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
+ if (a === b) return a !== 0 || 1 / a == 1 / b;
+ // A strict comparison is necessary because `null == undefined`.
+ if (a == null || b == null) return a === b;
+ // Unwrap any wrapped objects.
+ if (a._chain) a = a._wrapped;
+ if (b._chain) b = b._wrapped;
+ // Invoke a custom `isEqual` method if one is provided.
+ if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
+ if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
+ // Compare `[[Class]]` names.
+ var className = toString.call(a);
+ if (className != toString.call(b)) return false;
+ switch (className) {
+ // Strings, numbers, dates, and booleans are compared by value.
+ case '[object String]':
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
+ // equivalent to `new String("5")`.
+ return a == String(b);
+ case '[object Number]':
+ // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
+ // other numeric values.
+ return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
+ case '[object Date]':
+ case '[object Boolean]':
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
+ // millisecond representations. Note that invalid dates with millisecond representations
+ // of `NaN` are not equivalent.
+ return +a == +b;
+ // RegExps are compared by their source patterns and flags.
+ case '[object RegExp]':
+ return a.source == b.source &&
+ a.global == b.global &&
+ a.multiline == b.multiline &&
+ a.ignoreCase == b.ignoreCase;
+ }
+ if (typeof a != 'object' || typeof b != 'object') return false;
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+ var length = stack.length;
+ while (length--) {
+ // Linear search. Performance is inversely proportional to the number of
+ // unique nested structures.
+ if (stack[length] == a) return true;
+ }
+ // Add the first object to the stack of traversed objects.
+ stack.push(a);
+ var size = 0, result = true;
+ // Recursively compare objects and arrays.
+ if (className == '[object Array]') {
+ // Compare array lengths to determine if a deep comparison is necessary.
+ size = a.length;
+ result = size == b.length;
+ if (result) {
+ // Deep compare the contents, ignoring non-numeric properties.
+ while (size--) {
+ // Ensure commutative equality for sparse arrays.
+ if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
+ }
+ }
+ } else {
+ // Objects with different constructors are not equivalent.
+ if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
+ // Deep compare objects.
+ for (var key in a) {
+ if (_.has(a, key)) {
+ // Count the expected number of properties.
+ size++;
+ // Deep compare each member.
+ if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break;
+ }
+ }
+ // Ensure that both objects contain the same number of properties.
+ if (result) {
+ for (key in b) {
+ if (_.has(b, key) && !(size--)) break;
+ }
+ result = !size;
+ }
+ }
+ // Remove the first object from the stack of traversed objects.
+ stack.pop();
+ return result;
+ }
+
+ // Perform a deep comparison to check if two objects are equal.
+ _.isEqual = function(a, b) {
+ return eq(a, b, []);
+ };
+
+ // Is a given array, string, or object empty?
+ // An "empty" object has no enumerable own-properties.
+ _.isEmpty = function(obj) {
+ if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
+ for (var key in obj) if (_.has(obj, key)) return false;
+ return true;
+ };
+
+ // Is a given value a DOM element?
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType == 1);
+ };
+
+ // Is a given value an array?
+ // Delegates to ECMA5's native Array.isArray
+ _.isArray = nativeIsArray || function(obj) {
+ return toString.call(obj) == '[object Array]';
+ };
+
+ // Is a given variable an object?
+ _.isObject = function(obj) {
+ return obj === Object(obj);
+ };
+
+ // Is a given variable an arguments object?
+ _.isArguments = function(obj) {
+ return toString.call(obj) == '[object Arguments]';
+ };
+ if (!_.isArguments(arguments)) {
+ _.isArguments = function(obj) {
+ return !!(obj && _.has(obj, 'callee'));
+ };
+ }
+
+ // Is a given value a function?
+ _.isFunction = function(obj) {
+ return toString.call(obj) == '[object Function]';
+ };
+
+ // Is a given value a string?
+ _.isString = function(obj) {
+ return toString.call(obj) == '[object String]';
+ };
+
+ // Is a given value a number?
+ _.isNumber = function(obj) {
+ return toString.call(obj) == '[object Number]';
+ };
+
+ // Is the given value `NaN`?
+ _.isNaN = function(obj) {
+ // `NaN` is the only value for which `===` is not reflexive.
+ return obj !== obj;
+ };
+
+ // Is a given value a boolean?
+ _.isBoolean = function(obj) {
+ return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
+ };
+
+ // Is a given value a date?
+ _.isDate = function(obj) {
+ return toString.call(obj) == '[object Date]';
+ };
+
+ // Is the given value a regular expression?
+ _.isRegExp = function(obj) {
+ return toString.call(obj) == '[object RegExp]';
+ };
+
+ // Is a given value equal to null?
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+
+ // Is a given variable undefined?
+ _.isUndefined = function(obj) {
+ return obj === void 0;
+ };
+
+ // Has own property?
+ _.has = function(obj, key) {
+ return hasOwnProperty.call(obj, key);
+ };
+
+ // Utility Functions
+ // -----------------
+
+ // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
+ // previous owner. Returns a reference to the Underscore object.
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+
+ // Keep the identity function around for default iterators.
+ _.identity = function(value) {
+ return value;
+ };
+
+ // Run a function **n** times.
+ _.times = function (n, iterator, context) {
+ for (var i = 0; i < n; i++) iterator.call(context, i);
+ };
+
+ // Escape a string for HTML interpolation.
+ _.escape = function(string) {
+ return (''+string).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');
+ };
+
+ // Add your own custom functions to the Underscore object, ensuring that
+ // they're correctly added to the OOP wrapper as well.
+ _.mixin = function(obj) {
+ each(_.functions(obj), function(name){
+ addToWrapper(name, _[name] = obj[name]);
+ });
+ };
+
+ // Generate a unique integer id (unique within the entire client session).
+ // Useful for temporary DOM ids.
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = idCounter++;
+ return prefix ? prefix + id : id;
+ };
+
+ // By default, Underscore uses ERB-style template delimiters, change the
+ // following template settings to use alternative delimiters.
+ _.templateSettings = {
+ evaluate : /<%([\s\S]+?)%>/g,
+ interpolate : /<%=([\s\S]+?)%>/g,
+ escape : /<%-([\s\S]+?)%>/g
+ };
+
+ // When customizing `templateSettings`, if you don't want to define an
+ // interpolation, evaluation or escaping regex, we need one that is
+ // guaranteed not to match.
+ var noMatch = /.^/;
+
+ // Within an interpolation, evaluation, or escaping, remove HTML escaping
+ // that had been previously added.
+ var unescape = function(code) {
+ return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'");
+ };
+
+ // JavaScript micro-templating, similar to John Resig's implementation.
+ // Underscore templating handles arbitrary delimiters, preserves whitespace,
+ // and correctly escapes quotes within interpolated code.
+ _.template = function(str, data) {
+ var c = _.templateSettings;
+ var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
+ 'with(obj||{}){__p.push(\'' +
+ str.replace(/\\/g, '\\\\')
+ .replace(/'/g, "\\'")
+ .replace(c.escape || noMatch, function(match, code) {
+ return "',_.escape(" + unescape(code) + "),'";
+ })
+ .replace(c.interpolate || noMatch, function(match, code) {
+ return "'," + unescape(code) + ",'";
+ })
+ .replace(c.evaluate || noMatch, function(match, code) {
+ return "');" + unescape(code).replace(/[\r\n\t]/g, ' ') + ";__p.push('";
+ })
+ .replace(/\r/g, '\\r')
+ .replace(/\n/g, '\\n')
+ .replace(/\t/g, '\\t')
+ + "');}return __p.join('');";
+ var func = new Function('obj', '_', tmpl);
+ if (data) return func(data, _);
+ return function(data) {
+ return func.call(this, data, _);
+ };
+ };
+
+ // Add a "chain" function, which will delegate to the wrapper.
+ _.chain = function(obj) {
+ return _(obj).chain();
+ };
+
+ // The OOP Wrapper
+ // ---------------
+
+ // If Underscore is called as a function, it returns a wrapped object that
+ // can be used OO-style. This wrapper holds altered versions of all the
+ // underscore functions. Wrapped objects may be chained.
+ var wrapper = function(obj) { this._wrapped = obj; };
+
+ // Expose `wrapper.prototype` as `_.prototype`
+ _.prototype = wrapper.prototype;
+
+ // Helper function to continue chaining intermediate results.
+ var result = function(obj, chain) {
+ return chain ? _(obj).chain() : obj;
+ };
+
+ // A method to easily add functions to the OOP wrapper.
+ var addToWrapper = function(name, func) {
+ wrapper.prototype[name] = function() {
+ var args = slice.call(arguments);
+ unshift.call(args, this._wrapped);
+ return result(func.apply(_, args), this._chain);
+ };
+ };
+
+ // Add all of the Underscore functions to the wrapper object.
+ _.mixin(_);
+
+ // Add all mutator Array functions to the wrapper.
+ each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = ArrayProto[name];
+ wrapper.prototype[name] = function() {
+ var wrapped = this._wrapped;
+ method.apply(wrapped, arguments);
+ var length = wrapped.length;
+ if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0];
+ return result(wrapped, this._chain);
+ };
+ });
+
+ // Add all accessor Array functions to the wrapper.
+ each(['concat', 'join', 'slice'], function(name) {
+ var method = ArrayProto[name];
+ wrapper.prototype[name] = function() {
+ return result(method.apply(this._wrapped, arguments), this._chain);
+ };
+ });
+
+ // Start chaining a wrapped Underscore object.
+ wrapper.prototype.chain = function() {
+ this._chain = true;
+ return this;
+ };
+
+ // Extracts the result from a wrapped and chained object.
+ wrapper.prototype.value = function() {
+ return this._wrapped;
+ };
+
+}).call(this);
diff --git a/docs/build/html/_static/underscore.js b/docs/build/html/_static/underscore.js
new file mode 100644
index 0000000..5b55f32
--- /dev/null
+++ b/docs/build/html/_static/underscore.js
@@ -0,0 +1,31 @@
+// Underscore.js 1.3.1
+// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
+// Underscore is freely distributable under the MIT license.
+// Portions of Underscore are inspired or borrowed from Prototype,
+// Oliver Steele's Functional, and John Resig's Micro-Templating.
+// For all details and documentation:
+// http://documentcloud.github.com/underscore
+(function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==
+c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,
+h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else r._=b;b.VERSION="1.3.1";var j=b.each=
+b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a==
+null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=
+function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e=
+e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck=
+function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,
+c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};
+b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments,
+1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};
+b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};
+b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e /g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a),
+function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+
+u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]=
+function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=
+true;return this};m.prototype.value=function(){return this._wrapped}}).call(this);
diff --git a/docs/build/html/_static/up-pressed.png b/docs/build/html/_static/up-pressed.png
new file mode 100644
index 0000000..99e7210
Binary files /dev/null and b/docs/build/html/_static/up-pressed.png differ
diff --git a/docs/build/html/_static/up.png b/docs/build/html/_static/up.png
new file mode 100644
index 0000000..26de002
Binary files /dev/null and b/docs/build/html/_static/up.png differ
diff --git a/docs/build/html/_static/websupport.js b/docs/build/html/_static/websupport.js
new file mode 100644
index 0000000..98e7f40
--- /dev/null
+++ b/docs/build/html/_static/websupport.js
@@ -0,0 +1,808 @@
+/*
+ * websupport.js
+ * ~~~~~~~~~~~~~
+ *
+ * sphinx.websupport utilities for all documentation.
+ *
+ * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+(function($) {
+ $.fn.autogrow = function() {
+ return this.each(function() {
+ var textarea = this;
+
+ $.fn.autogrow.resize(textarea);
+
+ $(textarea)
+ .focus(function() {
+ textarea.interval = setInterval(function() {
+ $.fn.autogrow.resize(textarea);
+ }, 500);
+ })
+ .blur(function() {
+ clearInterval(textarea.interval);
+ });
+ });
+ };
+
+ $.fn.autogrow.resize = function(textarea) {
+ var lineHeight = parseInt($(textarea).css('line-height'), 10);
+ var lines = textarea.value.split('\n');
+ var columns = textarea.cols;
+ var lineCount = 0;
+ $.each(lines, function() {
+ lineCount += Math.ceil(this.length / columns) || 1;
+ });
+ var height = lineHeight * (lineCount + 1);
+ $(textarea).css('height', height);
+ };
+})(jQuery);
+
+(function($) {
+ var comp, by;
+
+ function init() {
+ initEvents();
+ initComparator();
+ }
+
+ function initEvents() {
+ $(document).on("click", 'a.comment-close', function(event) {
+ event.preventDefault();
+ hide($(this).attr('id').substring(2));
+ });
+ $(document).on("click", 'a.vote', function(event) {
+ event.preventDefault();
+ handleVote($(this));
+ });
+ $(document).on("click", 'a.reply', function(event) {
+ event.preventDefault();
+ openReply($(this).attr('id').substring(2));
+ });
+ $(document).on("click", 'a.close-reply', function(event) {
+ event.preventDefault();
+ closeReply($(this).attr('id').substring(2));
+ });
+ $(document).on("click", 'a.sort-option', function(event) {
+ event.preventDefault();
+ handleReSort($(this));
+ });
+ $(document).on("click", 'a.show-proposal', function(event) {
+ event.preventDefault();
+ showProposal($(this).attr('id').substring(2));
+ });
+ $(document).on("click", 'a.hide-proposal', function(event) {
+ event.preventDefault();
+ hideProposal($(this).attr('id').substring(2));
+ });
+ $(document).on("click", 'a.show-propose-change', function(event) {
+ event.preventDefault();
+ showProposeChange($(this).attr('id').substring(2));
+ });
+ $(document).on("click", 'a.hide-propose-change', function(event) {
+ event.preventDefault();
+ hideProposeChange($(this).attr('id').substring(2));
+ });
+ $(document).on("click", 'a.accept-comment', function(event) {
+ event.preventDefault();
+ acceptComment($(this).attr('id').substring(2));
+ });
+ $(document).on("click", 'a.delete-comment', function(event) {
+ event.preventDefault();
+ deleteComment($(this).attr('id').substring(2));
+ });
+ $(document).on("click", 'a.comment-markup', function(event) {
+ event.preventDefault();
+ toggleCommentMarkupBox($(this).attr('id').substring(2));
+ });
+ }
+
+ /**
+ * Set comp, which is a comparator function used for sorting and
+ * inserting comments into the list.
+ */
+ function setComparator() {
+ // If the first three letters are "asc", sort in ascending order
+ // and remove the prefix.
+ if (by.substring(0,3) == 'asc') {
+ var i = by.substring(3);
+ comp = function(a, b) { return a[i] - b[i]; };
+ } else {
+ // Otherwise sort in descending order.
+ comp = function(a, b) { return b[by] - a[by]; };
+ }
+
+ // Reset link styles and format the selected sort option.
+ $('a.sel').attr('href', '#').removeClass('sel');
+ $('a.by' + by).removeAttr('href').addClass('sel');
+ }
+
+ /**
+ * Create a comp function. If the user has preferences stored in
+ * the sortBy cookie, use those, otherwise use the default.
+ */
+ function initComparator() {
+ by = 'rating'; // Default to sort by rating.
+ // If the sortBy cookie is set, use that instead.
+ if (document.cookie.length > 0) {
+ var start = document.cookie.indexOf('sortBy=');
+ if (start != -1) {
+ start = start + 7;
+ var end = document.cookie.indexOf(";", start);
+ if (end == -1) {
+ end = document.cookie.length;
+ by = unescape(document.cookie.substring(start, end));
+ }
+ }
+ }
+ setComparator();
+ }
+
+ /**
+ * Show a comment div.
+ */
+ function show(id) {
+ $('#ao' + id).hide();
+ $('#ah' + id).show();
+ var context = $.extend({id: id}, opts);
+ var popup = $(renderTemplate(popupTemplate, context)).hide();
+ popup.find('textarea[name="proposal"]').hide();
+ popup.find('a.by' + by).addClass('sel');
+ var form = popup.find('#cf' + id);
+ form.submit(function(event) {
+ event.preventDefault();
+ addComment(form);
+ });
+ $('#s' + id).after(popup);
+ popup.slideDown('fast', function() {
+ getComments(id);
+ });
+ }
+
+ /**
+ * Hide a comment div.
+ */
+ function hide(id) {
+ $('#ah' + id).hide();
+ $('#ao' + id).show();
+ var div = $('#sc' + id);
+ div.slideUp('fast', function() {
+ div.remove();
+ });
+ }
+
+ /**
+ * Perform an ajax request to get comments for a node
+ * and insert the comments into the comments tree.
+ */
+ function getComments(id) {
+ $.ajax({
+ type: 'GET',
+ url: opts.getCommentsURL,
+ data: {node: id},
+ success: function(data, textStatus, request) {
+ var ul = $('#cl' + id);
+ var speed = 100;
+ $('#cf' + id)
+ .find('textarea[name="proposal"]')
+ .data('source', data.source);
+
+ if (data.comments.length === 0) {
+ ul.html('No comments yet. ');
+ ul.data('empty', true);
+ } else {
+ // If there are comments, sort them and put them in the list.
+ var comments = sortComments(data.comments);
+ speed = data.comments.length * 100;
+ appendComments(comments, ul);
+ ul.data('empty', false);
+ }
+ $('#cn' + id).slideUp(speed + 200);
+ ul.slideDown(speed);
+ },
+ error: function(request, textStatus, error) {
+ showError('Oops, there was a problem retrieving the comments.');
+ },
+ dataType: 'json'
+ });
+ }
+
+ /**
+ * Add a comment via ajax and insert the comment into the comment tree.
+ */
+ function addComment(form) {
+ var node_id = form.find('input[name="node"]').val();
+ var parent_id = form.find('input[name="parent"]').val();
+ var text = form.find('textarea[name="comment"]').val();
+ var proposal = form.find('textarea[name="proposal"]').val();
+
+ if (text == '') {
+ showError('Please enter a comment.');
+ return;
+ }
+
+ // Disable the form that is being submitted.
+ form.find('textarea,input').attr('disabled', 'disabled');
+
+ // Send the comment to the server.
+ $.ajax({
+ type: "POST",
+ url: opts.addCommentURL,
+ dataType: 'json',
+ data: {
+ node: node_id,
+ parent: parent_id,
+ text: text,
+ proposal: proposal
+ },
+ success: function(data, textStatus, error) {
+ // Reset the form.
+ if (node_id) {
+ hideProposeChange(node_id);
+ }
+ form.find('textarea')
+ .val('')
+ .add(form.find('input'))
+ .removeAttr('disabled');
+ var ul = $('#cl' + (node_id || parent_id));
+ if (ul.data('empty')) {
+ $(ul).empty();
+ ul.data('empty', false);
+ }
+ insertComment(data.comment);
+ var ao = $('#ao' + node_id);
+ ao.find('img').attr({'src': opts.commentBrightImage});
+ if (node_id) {
+ // if this was a "root" comment, remove the commenting box
+ // (the user can get it back by reopening the comment popup)
+ $('#ca' + node_id).slideUp();
+ }
+ },
+ error: function(request, textStatus, error) {
+ form.find('textarea,input').removeAttr('disabled');
+ showError('Oops, there was a problem adding the comment.');
+ }
+ });
+ }
+
+ /**
+ * Recursively append comments to the main comment list and children
+ * lists, creating the comment tree.
+ */
+ function appendComments(comments, ul) {
+ $.each(comments, function() {
+ var div = createCommentDiv(this);
+ ul.append($(document.createElement('li')).html(div));
+ appendComments(this.children, div.find('ul.comment-children'));
+ // To avoid stagnating data, don't store the comments children in data.
+ this.children = null;
+ div.data('comment', this);
+ });
+ }
+
+ /**
+ * After adding a new comment, it must be inserted in the correct
+ * location in the comment tree.
+ */
+ function insertComment(comment) {
+ var div = createCommentDiv(comment);
+
+ // To avoid stagnating data, don't store the comments children in data.
+ comment.children = null;
+ div.data('comment', comment);
+
+ var ul = $('#cl' + (comment.node || comment.parent));
+ var siblings = getChildren(ul);
+
+ var li = $(document.createElement('li'));
+ li.hide();
+
+ // Determine where in the parents children list to insert this comment.
+ for(i=0; i < siblings.length; i++) {
+ if (comp(comment, siblings[i]) <= 0) {
+ $('#cd' + siblings[i].id)
+ .parent()
+ .before(li.html(div));
+ li.slideDown('fast');
+ return;
+ }
+ }
+
+ // If we get here, this comment rates lower than all the others,
+ // or it is the only comment in the list.
+ ul.append(li.html(div));
+ li.slideDown('fast');
+ }
+
+ function acceptComment(id) {
+ $.ajax({
+ type: 'POST',
+ url: opts.acceptCommentURL,
+ data: {id: id},
+ success: function(data, textStatus, request) {
+ $('#cm' + id).fadeOut('fast');
+ $('#cd' + id).removeClass('moderate');
+ },
+ error: function(request, textStatus, error) {
+ showError('Oops, there was a problem accepting the comment.');
+ }
+ });
+ }
+
+ function deleteComment(id) {
+ $.ajax({
+ type: 'POST',
+ url: opts.deleteCommentURL,
+ data: {id: id},
+ success: function(data, textStatus, request) {
+ var div = $('#cd' + id);
+ if (data == 'delete') {
+ // Moderator mode: remove the comment and all children immediately
+ div.slideUp('fast', function() {
+ div.remove();
+ });
+ return;
+ }
+ // User mode: only mark the comment as deleted
+ div
+ .find('span.user-id:first')
+ .text('[deleted]').end()
+ .find('div.comment-text:first')
+ .text('[deleted]').end()
+ .find('#cm' + id + ', #dc' + id + ', #ac' + id + ', #rc' + id +
+ ', #sp' + id + ', #hp' + id + ', #cr' + id + ', #rl' + id)
+ .remove();
+ var comment = div.data('comment');
+ comment.username = '[deleted]';
+ comment.text = '[deleted]';
+ div.data('comment', comment);
+ },
+ error: function(request, textStatus, error) {
+ showError('Oops, there was a problem deleting the comment.');
+ }
+ });
+ }
+
+ function showProposal(id) {
+ $('#sp' + id).hide();
+ $('#hp' + id).show();
+ $('#pr' + id).slideDown('fast');
+ }
+
+ function hideProposal(id) {
+ $('#hp' + id).hide();
+ $('#sp' + id).show();
+ $('#pr' + id).slideUp('fast');
+ }
+
+ function showProposeChange(id) {
+ $('#pc' + id).hide();
+ $('#hc' + id).show();
+ var textarea = $('#pt' + id);
+ textarea.val(textarea.data('source'));
+ $.fn.autogrow.resize(textarea[0]);
+ textarea.slideDown('fast');
+ }
+
+ function hideProposeChange(id) {
+ $('#hc' + id).hide();
+ $('#pc' + id).show();
+ var textarea = $('#pt' + id);
+ textarea.val('').removeAttr('disabled');
+ textarea.slideUp('fast');
+ }
+
+ function toggleCommentMarkupBox(id) {
+ $('#mb' + id).toggle();
+ }
+
+ /** Handle when the user clicks on a sort by link. */
+ function handleReSort(link) {
+ var classes = link.attr('class').split(/\s+/);
+ for (var i=0; iThank you! Your comment will show up '
+ + 'once it is has been approved by a moderator. ');
+ }
+ // Prettify the comment rating.
+ comment.pretty_rating = comment.rating + ' point' +
+ (comment.rating == 1 ? '' : 's');
+ // Make a class (for displaying not yet moderated comments differently)
+ comment.css_class = comment.displayed ? '' : ' moderate';
+ // Create a div for this comment.
+ var context = $.extend({}, opts, comment);
+ var div = $(renderTemplate(commentTemplate, context));
+
+ // If the user has voted on this comment, highlight the correct arrow.
+ if (comment.vote) {
+ var direction = (comment.vote == 1) ? 'u' : 'd';
+ div.find('#' + direction + 'v' + comment.id).hide();
+ div.find('#' + direction + 'u' + comment.id).show();
+ }
+
+ if (opts.moderator || comment.text != '[deleted]') {
+ div.find('a.reply').show();
+ if (comment.proposal_diff)
+ div.find('#sp' + comment.id).show();
+ if (opts.moderator && !comment.displayed)
+ div.find('#cm' + comment.id).show();
+ if (opts.moderator || (opts.username == comment.username))
+ div.find('#dc' + comment.id).show();
+ }
+ return div;
+ }
+
+ /**
+ * A simple template renderer. Placeholders such as <%id%> are replaced
+ * by context['id'] with items being escaped. Placeholders such as <#id#>
+ * are not escaped.
+ */
+ function renderTemplate(template, context) {
+ var esc = $(document.createElement('div'));
+
+ function handle(ph, escape) {
+ var cur = context;
+ $.each(ph.split('.'), function() {
+ cur = cur[this];
+ });
+ return escape ? esc.text(cur || "").html() : cur;
+ }
+
+ return template.replace(/<([%#])([\w\.]*)\1>/g, function() {
+ return handle(arguments[2], arguments[1] == '%' ? true : false);
+ });
+ }
+
+ /** Flash an error message briefly. */
+ function showError(message) {
+ $(document.createElement('div')).attr({'class': 'popup-error'})
+ .append($(document.createElement('div'))
+ .attr({'class': 'error-message'}).text(message))
+ .appendTo('body')
+ .fadeIn("slow")
+ .delay(2000)
+ .fadeOut("slow");
+ }
+
+ /** Add a link the user uses to open the comments popup. */
+ $.fn.comment = function() {
+ return this.each(function() {
+ var id = $(this).attr('id').substring(1);
+ var count = COMMENT_METADATA[id];
+ var title = count + ' comment' + (count == 1 ? '' : 's');
+ var image = count > 0 ? opts.commentBrightImage : opts.commentImage;
+ var addcls = count == 0 ? ' nocomment' : '';
+ $(this)
+ .append(
+ $(document.createElement('a')).attr({
+ href: '#',
+ 'class': 'sphinx-comment-open' + addcls,
+ id: 'ao' + id
+ })
+ .append($(document.createElement('img')).attr({
+ src: image,
+ alt: 'comment',
+ title: title
+ }))
+ .click(function(event) {
+ event.preventDefault();
+ show($(this).attr('id').substring(2));
+ })
+ )
+ .append(
+ $(document.createElement('a')).attr({
+ href: '#',
+ 'class': 'sphinx-comment-close hidden',
+ id: 'ah' + id
+ })
+ .append($(document.createElement('img')).attr({
+ src: opts.closeCommentImage,
+ alt: 'close',
+ title: 'close'
+ }))
+ .click(function(event) {
+ event.preventDefault();
+ hide($(this).attr('id').substring(2));
+ })
+ );
+ });
+ };
+
+ var opts = {
+ processVoteURL: '/_process_vote',
+ addCommentURL: '/_add_comment',
+ getCommentsURL: '/_get_comments',
+ acceptCommentURL: '/_accept_comment',
+ deleteCommentURL: '/_delete_comment',
+ commentImage: '/static/_static/comment.png',
+ closeCommentImage: '/static/_static/comment-close.png',
+ loadingImage: '/static/_static/ajax-loader.gif',
+ commentBrightImage: '/static/_static/comment-bright.png',
+ upArrow: '/static/_static/up.png',
+ downArrow: '/static/_static/down.png',
+ upArrowPressed: '/static/_static/up-pressed.png',
+ downArrowPressed: '/static/_static/down-pressed.png',
+ voting: false,
+ moderator: false
+ };
+
+ if (typeof COMMENT_OPTIONS != "undefined") {
+ opts = jQuery.extend(opts, COMMENT_OPTIONS);
+ }
+
+ var popupTemplate = '\
+ ';
+
+ var commentTemplate = '\
+ \
+ ';
+
+ var replyTemplate = '\
+ \
+ \
+ \
+
\
+ ';
+
+ $(document).ready(function() {
+ init();
+ });
+})(jQuery);
+
+$(document).ready(function() {
+ // add comment anchors for all paragraphs that are commentable
+ $('.sphinx-has-comment').comment();
+
+ // highlight search words in search results
+ $("div.context").each(function() {
+ var params = $.getQueryParameters();
+ var terms = (params.q) ? params.q[0].split(/\s+/) : [];
+ var result = $(this);
+ $.each(terms, function() {
+ result.highlightText(this.toLowerCase(), 'highlighted');
+ });
+ });
+
+ // directly open comment window if requested
+ var anchor = document.location.hash;
+ if (anchor.substring(0, 9) == '#comment-') {
+ $('#ao' + anchor.substring(9)).click();
+ document.location.hash = '#s' + anchor.substring(9);
+ }
+});
diff --git a/docs/build/html/com.html b/docs/build/html/com.html
new file mode 100644
index 0000000..a22e92f
--- /dev/null
+++ b/docs/build/html/com.html
@@ -0,0 +1,161 @@
+
+
+
+
+
+
+
+ 8. windows.com - Component Object Model — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/debug.html b/docs/build/html/debug.html
new file mode 100644
index 0000000..f2bc4f3
--- /dev/null
+++ b/docs/build/html/debug.html
@@ -0,0 +1,508 @@
+
+
+
+
+
+
+
+ 7. windows.debug – Debugging — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The Debugger is the base class to perform the debugging of a remote process.
+The Debugger have some functions called on given event that can be implemented by subclasses.
+
All Memory-breakpoint are disabled when callind a public callback or a breakpoint trigger() function.
+
This means that those methods see the original current_process memory access rights.
+
+
+class windows.debug.Debugger( target ) [source]
+A debugger based on standard Win32 API. Handle :
+
+Standard BP (int3)
+Hardware-Exec BP (DrX)
+Memory BP (virtual_protect)
+
+
+
+__init__( target ) [source]
+target must be a debuggable WinProcess .
+
+
+
+
+classmethod attach( target ) [source]
+attach to target (must be a WinProcess )
+
+
+
+
+
+classmethod debug( path , args=None , dwCreationFlags=0 , show_windows=False ) [source]
+Create a process and debug it.
+
+
+
+
+
+loop( ) [source]
+Debugging loop: handle event / dispatch to breakpoint. Returns when all targets are dead
+
+
+
+
+add_bp( bp , addr=None , type=None , target=None ) [source]
+Add a breakpoint, bp can be:
+
+a Breakpoint (addr and type must be None )
+any callable (addr and type must NOT be None ) (NON-TESTED)
+
+If the bp type is STANDARD_BP or MEMORY_BREAKPOINT , target can be None (all targets) or a process.
+If the bp type is HARDWARE_EXEC_BP , target can be None (all targets), a process or a thread.
+
+
+
+
+del_bp( bp , targets=None ) [source]
+Delete a breakpoint, if targets is None : delete it from all targets
+
+
+
+
+single_step( ) [source]
+Make the current_thread single_step . Debugger.on_single_step will be called after that
+
+
+
+
+get_memory_breakpoint_at( addr , process=None ) [source]
+Get the memory breakpoint that handle addr
+Return values are:
+
+
+False if the page has no memory breakpoint (real fault)
+None if the page as memBP but None handle addr
+bp the MemBP that handle addr
+
+
+
+
+
+
+disable_all_memory_breakpoints( target=None ) [source]
+Restore all pages to their original access rights.
+If target is None , use current_process
+
+
+
+
+
+restore_all_memory_breakpoints( data , target=None ) [source]
+Re-setup all memory breakpoints, affecting pages access rights.
+If target is None , use current_process
+data is the result of the corresponding call to disable_all_memory_breakpoints()
+
+
+
+
+DisabledMemoryBreakpoint( *args , **kwds ) [source]
+A context-manager that disable all memory breakpoints and restore them on exit
+
+
+
+
+get_exception_bitness( exc ) [source]
+Return the bitness in which the exception occured.
+Useful when debugingg a 32b process from a 64bits one
+
+
+
+
+Returns: int – 32 or 64
+
+
+
+
+
+
+
+on_exception( exception ) [source]
+Called on exception event other that known breakpoint or requested single step. exception is one of the following type:
+
+
+The default behaviour is to return DBG_CONTINUE for the known exception code
+and DBG_EXCEPTION_NOT_HANDLED else
+
+
+
+
+on_single_step( exception ) [source]
+Called on requested single step``exception`` is one of the following type:
+
+
+There is no default implementation, if you use Debugger.single_step() you should implement on_single_step
+
+
+
+
+on_create_process( create_process ) [source]
+Called on create_process event (for param type see https://msdn.microsoft.com/en-us/library/windows/desktop/ms679286(v=vs.85).aspx )
+
+
+
+
+on_exit_process( exit_process ) [source]
+Called on exit_process event (for param type see https://msdn.microsoft.com/en-us/library/windows/desktop/ms679334(v=vs.85).aspx )
+
+
+
+
+on_create_thread( create_thread ) [source]
+Called on create_thread event (for param type see https://msdn.microsoft.com/en-us/library/windows/desktop/ms679287(v=vs.85).aspx )
+
+
+
+
+on_exit_thread( exit_thread ) [source]
+Called on exit_thread event (for param type see https://msdn.microsoft.com/en-us/library/windows/desktop/ms679335(v=vs.85).aspx )
+
+
+
+
+on_load_dll( load_dll ) [source]
+Called on load_dll event (for param type see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680351(v=vs.85).aspx )
+
+
+
+
+on_unload_dll( unload_dll ) [source]
+Called on unload_dll event (for param type see https://msdn.microsoft.com/en-us/library/windows/desktop/ms681403(v=vs.85).aspx )
+
+
+
+
+on_output_debug_string( debug_string ) [source]
+Called on debug_string event (for param type see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680545(v=vs.85).aspx )
+
+
+
+
+on_rip( rip_info ) [source]
+Called on rip_info event (for param type see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680587(v=vs.85).aspx )
+
+
+
+
+
+
+
+
+
The Debugger is the base class to perform the debugging the current process.
+It is based on VectoredException() (see VectoredException() )
+
There is not much documentation for now as the code might change soon.
+
+
+class windows.debug.LocalDebugger[source]
+A debugger interface around AddVectoredExceptionHandler() .
+Handle:
+
+
+Standard BP (int3)
+Hardware-Exec BP (DrX)
+
+
+
+
+add_bp( bp , targets=None ) [source]
+Add a breakpoint, bp is a “class:Breakpoint
+If the bp type is STANDARD_BP , target must be None.
+If the bp type is HARDWARE_EXEC_BP , target can be None (all threads), or some threads of the process
+
+
+
+
+del_bp( bp ) [source]
+Delete a breakpoint
+
+
+
+
+get_exception_code( ) [source]
+Return ExceptionCode of current exception
+
+
+
+
+get_exception_context( ) [source]
+Return context of current exception
+
+
+
+
+on_exception( exc ) [source]
+Called on exception
+
+
+
+
+single_step( ) [source]
+Make the current thread to single step
+
+
+
+
+
+
+
+
Standard breakpoints types expect an address as argument.
+
An address can be:
+
+
+
When a breakpoint is hit, its trigger function is called with the debugger and a
+DEBUG_EXECEPTION_EVENT structure as argument.
+
+
+class windows.debug.Breakpoint( addr ) [source]
+An standard (Int3) breakpoint (type == STANDARD_BP )
+
+
+trigger( dbg , exception ) [source]
+Called when breakpoint is hit
+
+
+
+
+
+
+class windows.debug.HXBreakpoint( addr ) [source]
+An hardware-execution breakpoint (type == HARDWARE_EXEC_BP )
+
+
+trigger( dbg , exception )
+Called when breakpoint is hit
+
+
+
+
+
+
+class windows.debug.MemoryBreakpoint( addr , size=None , events=None ) [source]
+A memory breakpoint (type == MEMORY_BREAKPOINT )
+
+
+__init__( addr , size=None , events=None ) [source]
+size : the size of the memory breakpoint.
+events : a string representing the events that interest the BP (any of “RWX”)
+
+
+
+
+trigger( dbg , exception ) [source]
+Called when breakpoint is hit
+
+
+
+
+
+
Note
+
MemoryBreakpoint are triggered based on the fault address only (as I don’t know a way to get the size of the read/write causing the fault without embedding a disassembler).
+
This means that a MEMBP at address X won’t be triggered by a write of size 4 at address X - 1 . it’s sad I know.
+
+
+
+class windows.debug.FunctionBP( target , addr=None ) [source]
+A breakpoint that accept a function from windows.winproxy and able to:
+
+Extract the arguments of the functions
+Break at the return of the function
+
+
+
+break_on_ret( dbg , exception )
+Setup a breakpoint at the return address of the function, this breakpoint will call ret_trigger()
+
+
+
+
+Extracts the functions parameters in an OrderedDict
+
+
+
+
+ret_trigger( dbg , exception )
+Called at the return of the function if break_on_ret() was called
+
+
+
+
+trigger( dbg , exception )
+Called when breakpoint is hit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/exception.html b/docs/build/html/exception.html
new file mode 100644
index 0000000..f405fd7
--- /dev/null
+++ b/docs/build/html/exception.html
@@ -0,0 +1,646 @@
+
+
+
+
+
+
+
+ 2.4. Exception and Context related structures — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2.4. Exception and Context related structures
+
This module regroups all the Exception/Context related structures and functions.
+Most of the structures are the Windows structure with a prefix E (For enhanced)
+
Those structure have the same fields that the normal windows ones but their types might vary for a simpler use.
+
This module also define the decorator VectoredException() which allows to play with Vectored Exception Handler in Python
+
+
+
2.4.1. Exception Records
+
+
+class windows.winobject.exception.EEXCEPTION_RECORD[source]
+Enhanced exception record
+
+
+ExceptionAddress
+The Exception Address
+
+
+
+
+
+ExceptionCode
+The Exception code
+
+
+
+
+
+fields = ['ExceptionCode', 'ExceptionFlags', 'ExceptionRecord', 'ExceptionAddress', 'NumberParameters', 'ExceptionInformation']
+The fields of the structure
+
+
+
+
+
+
+class windows.winobject.exception.EEXCEPTION_RECORD32[source]
+Enhanced exception record (32bits)
+
+
+ExceptionAddress
+The Exception Address
+
+
+
+
+
+ExceptionCode
+The Exception code
+
+
+
+
+
+fields = ['ExceptionCode', 'ExceptionFlags', 'ExceptionRecord', 'ExceptionAddress', 'NumberParameters', 'ExceptionInformation']
+The fields of the structure
+
+
+
+
+
+
+class windows.winobject.exception.EEXCEPTION_RECORD64[source]
+Enhanced exception record (64bits)
+
+
+ExceptionAddress
+The Exception Address
+
+
+
+
+
+ExceptionCode
+The Exception code
+
+
+
+
+
+fields = ['ExceptionCode', 'ExceptionFlags', 'ExceptionRecord', 'ExceptionAddress', 'NumberParameters', '__unusedAlignment', 'ExceptionInformation']
+The fields of the structure
+
+
+
+
+
+
+
2.4.2. EXCEPTION DEBUG INFO
+
+
+class windows.winobject.exception.EEXCEPTION_DEBUG_INFO32[source]
+Enhanced Debug info
+
+
+ExceptionRecord
+
+
+
+
+
+fields = ['ExceptionRecord', 'dwFirstChance']
+The fields of the structure
+
+
+
+
+
+
+class windows.winobject.exception.EEXCEPTION_DEBUG_INFO64[source]
+Enhanced Debug info
+
+
+ExceptionRecord
+
+
+
+
+
+fields = ['ExceptionRecord', 'dwFirstChance']
+The fields of the structure
+
+
+
+
+
+
+
2.4.3. Context
+
+
+class windows.winobject.exception.ECONTEXT32[source]
+
+
+EDr7
+Enhanced view of the DR7 register (you also have Dr7 for the raw value)
+
+
+
+
+
+EEFlags
+Enhanced view of the Eflags (you also have EFlags for the raw value)
+
+
+
+
+
+dump( to_dump=None )
+Dump (print) the current context
+
+
+
+
+fields = ['ContextFlags', 'Dr0', 'Dr1', 'Dr2', 'Dr3', 'Dr6', 'Dr7', 'FloatSave', 'SegGs', 'SegFs', 'SegEs', 'SegDs', 'Edi', 'Esi', 'Ebx', 'Edx', 'Ecx', 'Eax', 'Ebp', 'Eip', 'SegCs', 'EFlags', 'Esp', 'SegSs', 'ExtendedRegisters']
+The fields of the structure
+
+
+
+
+func_result
+Function Resultat register (EAX or RAX)
+
+
+
+
+pc
+Program Counter register (EIP or RIP)
+
+
+
+
+regs( to_dump=None )
+Return the name and values of the registers
+
+
+
+
+Returns: [(reg_name, value)] – A list of tuple
+
+
+
+
+
+
+
+sp
+Stack Pointer register (ESP or RSP)
+
+
+
+
+
+
+class windows.winobject.exception.ECONTEXTWOW64[source]
+
+
+EDr7
+Enhanced view of the DR7 register (you also have Dr7 for the raw value)
+
+
+
+
+
+EEFlags
+Enhanced view of the Eflags (you also have EFlags for the raw value)
+
+
+
+
+
+dump( to_dump=None )
+Dump (print) the current context
+
+
+
+
+fields = ['ContextFlags', 'Dr0', 'Dr1', 'Dr2', 'Dr3', 'Dr6', 'Dr7', 'FloatSave', 'SegGs', 'SegFs', 'SegEs', 'SegDs', 'Edi', 'Esi', 'Ebx', 'Edx', 'Ecx', 'Eax', 'Ebp', 'Eip', 'SegCs', 'EFlags', 'Esp', 'SegSs', 'ExtendedRegisters']
+The fields of the structure
+
+
+
+
+func_result
+Function Resultat register (EAX or RAX)
+
+
+
+
+pc
+Program Counter register (EIP or RIP)
+
+
+
+
+regs( to_dump=None )
+Return the name and values of the registers
+
+
+
+
+Returns: [(reg_name, value)] – A list of tuple
+
+
+
+
+
+
+
+sp
+Stack Pointer register (ESP or RSP)
+
+
+
+
+
+
+class windows.winobject.exception.ECONTEXT64[source]
+
+
+EDr7
+Enhanced view of the DR7 register (you also have Dr7 for the raw value)
+
+
+
+
+
+EEFlags
+Enhanced view of the Eflags (you also have EFlags for the raw value)
+
+
+
+
+
+dump( to_dump=None )
+Dump (print) the current context
+
+
+
+
+fields = ['P1Home', 'P2Home', 'P3Home', 'P4Home', 'P5Home', 'P6Home', 'ContextFlags', 'MxCsr', 'SegCs', 'SegDs', 'SegEs', 'SegFs', 'SegGs', 'SegSs', 'EFlags', 'Dr0', 'Dr1', 'Dr2', 'Dr3', 'Dr6', 'Dr7', 'Rax', 'Rcx', 'Rdx', 'Rbx', 'Rsp', 'Rbp', 'Rsi', 'Rdi', 'R8', 'R9', 'R10', 'R11', 'R12', 'R13', 'R14', 'R15', 'Rip', 'DUMMYUNIONNAME', 'VectorRegister', 'VectorControl', 'DebugControl', 'LastBranchToRip', 'LastBranchFromRip', 'LastExceptionToRip', 'LastExceptionFromRip']
+The fields of the structure
+
+
+
+
+func_result
+Function Resultat register (EAX or RAX)
+
+
+
+
+classmethod new_aligned( ) [source]
+Return a new ECONTEXT64 aligned on 16 bits
+temporary workaround or horrible hack ? choose your side
+
+
+
+
+pc
+Program Counter register (EIP or RIP)
+
+
+
+
+regs( to_dump=None )
+Return the name and values of the registers
+
+
+
+
+Returns: [(reg_name, value)] – A list of tuple
+
+
+
+
+
+
+
+sp
+Stack Pointer register (ESP or RSP)
+
+
+
+
+
+
+class windows.winobject.exception.EEflags[source]
+Flag view of the Eflags register
+
+
+fields = ['CF', 'RES_1', 'PF', 'RES_3', 'AF', 'RES_5', 'ZF', 'SF', 'TF', 'IF', 'DF', 'OF', 'IOPL_1', 'IOPL_2', 'NT', 'RES_15', 'RF', 'VM', 'AC', 'VIF', 'VIP', 'ID']
+The fields of the structure
+
+
+
+
+raw
+Raw value of the eflags
+
+
+
+
+
+
+
+class windows.winobject.exception.EDr7[source]
+Flag view of the DR7 register
+
+
+fields = ['L0', 'G0', 'L1', 'G1', 'L2', 'G2', 'L3', 'G3', 'LE', 'GE', 'RES_1', 'GD', 'RES_1', 'RW0', 'LEN0', 'RW1', 'LEN1', 'RW2', 'LEN2', 'RW3', 'LEN3']
+The fields of the structure
+
+
+
+
+
+
+
2.4.4. EXCEPTION POINTERS
+
+
+class windows.winobject.exception.EEXCEPTION_POINTERS[source]
+
+
+ExceptionRecord
+
+
+
+
+
+ContextRecord
+
+
+
+
+
+dump( ) [source]
+Dump (print) the EEXCEPTION_POINTERS
+
+
+
+
+
+
+
2.4.5. Vectored Exception
+
+
+
+class windows.winobject.exception.VectoredException[source]
+A decorator that create a callable which can be passed to AddVectoredExceptionHandler()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/genindex.html b/docs/build/html/genindex.html
new file mode 100644
index 0000000..edc7964
--- /dev/null
+++ b/docs/build/html/genindex.html
@@ -0,0 +1,2059 @@
+
+
+
+
+
+
+
+
+ Index — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index
+
+
+
_
+ |
A
+ |
B
+ |
C
+ |
D
+ |
E
+ |
F
+ |
G
+ |
H
+ |
I
+ |
K
+ |
L
+ |
M
+ |
N
+ |
O
+ |
P
+ |
Q
+ |
R
+ |
S
+ |
T
+ |
U
+ |
V
+ |
W
+ |
X
+
+
+
_
+
+
+
A
+
+
+
B
+
+
+
C
+
+
+
D
+
+
+
E
+
+
+
F
+
+
+
G
+
+
+
H
+
+
+
I
+
+
+
K
+
+
+
L
+
+
+
M
+
+
+
N
+
+
+
O
+
+
+
P
+
+
+
Q
+
+
+
R
+
+
+
S
+
+
+
T
+
+
+
U
+
+
+
V
+
+
+
W
+
+
+
X
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/handle.html b/docs/build/html/handle.html
new file mode 100644
index 0000000..1a8f421
--- /dev/null
+++ b/docs/build/html/handle.html
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+ 2.10. Handle – Processes handles — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2.10. Handle – Processes handles
+
+
+
+class windows.winobject.handle.Handle[source]
+A handle of the system
+
+
+local_handle
+A local copy of the handle, acquired with DuplicateHandle
+
+
+
+
+
+name
+The name of the handle
+
+
+
+
+
+process
+The process possessing the handle
+
+
+
+
+
+type
+The type of the handle
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/iat_hook.html b/docs/build/html/iat_hook.html
new file mode 100644
index 0000000..c6cfe65
--- /dev/null
+++ b/docs/build/html/iat_hook.html
@@ -0,0 +1,251 @@
+
+
+
+
+
+
+
+ 9. IAT hooking — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
9. IAT hooking
+
+
+
9.1. Putting an IAT hook
+
To setup your IAT hook you just need:
+
+
+
You just need to use the function windows.pe_parse.IATEntry.set_hook()
+
Putting a hook:
+
import windows
+from windows.hooks import *
+
+@CreateFileACallback
+def createfile_callback ( lpFileName , dwDesiredAccess , dwShareMode , lpSecurityAttributes , dwCreationDisposition , dwFlagsAndAttributes , hTemplateFile , real_function ):
+ print ( "Trying to open {0} " . format ( lpFileName ))
+ if "secret" in lpFileName :
+ return 0xffffffff
+ return real_function ()
+
+my_exe = windows . current_process . peb . modules [ 0 ]
+imp = my_exe . pe . imports
+
+iat_create_file = [ entry for entry in imp [ 'kernel32.dll' ] if entry . name == "CreateFileA" ]
+iat_create_file . set_hook ( createfile_callback )
+
+
+
+
+
9.2. Hook protocol
+
+
9.2.1. Callback arguments
+
A hook callback must have the same number of argument as the hooked API, PLUS a last argument real_function .
+
The real_function argument is a callable that represent the hooked API, it can be called in two ways:
+
+
+Without argument, the call will be done with the argument originaly passed to your callback. This allows simple redirection to the real API.
+With arguments it will simply call the API with these.
+
+
+
Example:
+
def createfile_callback ( lpFileName , dwDesiredAccess , dwShareMode , lpSecurityAttributes , dwCreationDisposition , dwFlagsAndAttributes , hTemplateFile , real_function ):
+ print ( "Trying to open {0} " . format ( lpFileName ))
+ if "secret" in lpFileName :
+ return 0xffffffff
+ # Perform the real call
+ return real_function ()
+
+
+
A hook callback must also embed some Type Information
+
+
+
+
+
+
+
+class windows.hooks.Callback( *types ) [source]
+Give type information to hook callback
+
+
+
+
+class windows.hooks.IATHook( IAT_entry , callback , types=None ) [source]
+Look at my hook <3
+
+
+disable( ) [source]
+Disable the IAT hook
+
+
+
+
+enable( ) [source]
+Enable the IAT hook: you MUST keep a reference to the IATHook while the hook is enabled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/index.html b/docs/build/html/index.html
new file mode 100644
index 0000000..fc44e46
--- /dev/null
+++ b/docs/build/html/index.html
@@ -0,0 +1,198 @@
+
+
+
+
+
+
+
+ Welcome to PythonForWindows’s documentation! — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Welcome to PythonForWindows’s documentation!
+
Contents:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/internals.html b/docs/build/html/internals.html
new file mode 100644
index 0000000..2138f9e
--- /dev/null
+++ b/docs/build/html/internals.html
@@ -0,0 +1,272 @@
+
+
+
+
+
+
+
+ 11. Internals — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
11. Internals
+
Because some horrible hacks of PythonForWindows are hidden and I wanted to talk about it.
+
+
11.1. remotectypes.py
+
Performing parsing of PEB / PE in remote process may be painful and i didn’t want
+to have two versions of all my parsing code.
+
So I made a wrapper around ctypes that is able to do two things:
+
+
+Transform a 32bits ctypes structure into a 64bits one and reverse
+
+
This is done by replacing the c_void_p /c_char_p by DWORD or
+QWORD and rewriting a wrapper around the ctypes POINTER and other stuff.
+It might not works for every structure by i didn’t have any problem for now.
+
+Read the memory in another process
+
+
For this one I rewrote a class that use the standard ctypes structure
+offset-size calculation, extracts those information when asked for a field and read it from the target process.
+We just need to take care of special cases: POINTER / ARRAY / STRING / ..
+
+
We also need to be carreful about the inheritance, we need to inherit from “hidden”
+ctypes classes to keep the magic working.
+
This module exports the following API:
+
+
+windows.remotectypes.transform_type_to_remote32bits( ftype ) [source]
+
+
+
+
+windows.remotectypes.transform_type_to_remote64bits( ftype ) [source]
+
+
+
Both functions return a class that represent the structure in a remote process.
+The class.__init__ accept two arguments:
+
+
+base_addr : the address of the object in the remote process
+target : an object with a method read_memory (so a windows.winobject.WinProcess in our case)
+
+
+
Example WinProcess.peb :
+
def peb ( self ):
+ if windows . current_process . bitness == 32 and self . bitness == 64 :
+ return RemotePEB64 ( self . peb_addr , self )
+ if windows . current_process . bitness == 64 and self . bitness == 32 :
+ return RemotePEB32 ( self . peb_addr , self )
+ return RemotePEB ( self . peb_addr , self )
+
+
+
I am pretty sure that this code does NOT handle all the cases, so it might break some day.
+
+
+
11.2. syswow64.py – Crossing the heaven gate
+
One of my goal with PythonForWindows is to have some abstraction of the bitness of the processes.
+It means being able to work on a 32bits Python or a 64bits Python .
+
In the case of a 32bits python on a 64bits system (SysWow64 ) it’s not trivial to perform operation on
+other 64bits processes. For example directly calling CreateRemoteThread() will not work.
+
To be able to perform those operation we must be able to execute code in the 64bits part of our
+SysWow64 process.
+
+
For that we need to jump to the 64bits segment of our process, execute some code then return.
+To do so, we need to use some far jump / far ret with the segments selector 0x23 (CS_32bits) and 0x33 (CS_64bits).
+
The generation of this is quite ugly in my case.
+This code is in:
+
+
+windows.syswow64.execute_64bits_code_from_syswow( ) [source]
+
+
+
Once we are able to execute some code in the 64bits part we need to create the code that will call our API (in NTDLL).
+To do that, I rely on the type information already present in the function of windows.winproxy .
+With these information we are able to know
+
+
+The name of the API
+The number of arguments
+
+
+
Then I generate the correct x64 stub (using windows.native_exec.simple_x64 ) with the function:
+
+
+windows.syswow64.generate_syswow64_call( ) [source]
+
+
+
One problem I encountered is that our function must be able to pass values of 64bits, so passing arguments by register is not possible.
+
For now I allocate a buffer where a python wrapper copy the parameters and the x64 stub retrieves them from here.
+
(It might be possible to do something by creating a WINCFUNC with only ULONG64 parameters).
+
+
+windows.syswow64.try_generate_stub_target( ) [source]
+
+
+
The final result is a Python function like the one in windows.winproxy
+
+
+It copies the arguments in the buffer
+Jumps on the 32->64 stub
+X64 bits code retrieves the arguments in the buffer and setup the registers and the stack for the call
+Calls the API
+Returns to 32bits mode.
+
+
+
+
+class windows.syswow64.Syswow64ApiProxy[source]
+
+
+
Existing function are:
+
+
+windows.syswow64.NtCreateThreadEx_32_to_64( ) [source]
+
+
+
+
+windows.syswow64.NtQueryInformationProcess_32_to_64( ) [source]
+
+
+
+
+windows.syswow64.NtQueryInformationThread_32_to_64( ) [source]
+
+
+
+
+windows.syswow64.NtQueryVirtualMemory_32_to_64( ) [source]
+
+
+
+
+windows.syswow64.NtGetContextThread_32_to_64( ) [source]
+
+
+
+
+windows.syswow64.NtSetContextThread_32_to_64( ) [source]
+
+
+
+
+windows.syswow64.LdrLoadDll_32_to_64( ) [source]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/native_exec.html b/docs/build/html/native_exec.html
new file mode 100644
index 0000000..7ce3a04
--- /dev/null
+++ b/docs/build/html/native_exec.html
@@ -0,0 +1,539 @@
+
+
+
+
+
+
+
+ 3. windows.native_exec – Native Code Execution — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
3. windows.native_exec – Native Code Execution
+
windows.native_exec allows to create Python functions calling native code.
+it also provides a simple assembler for x86 and x64.
+
windows.native_exec provides those functions:
+
+
+windows.native_exec.create_function( code , types ) [source]
+Create a python function that call raw machine code
+
+
+
+
+Parameters:
+code (str ) – Raw machine code that will be called
+types (list ) – Return type and parameters type (see ctypes )
+
+
+
+Returns: the created function
+
+
+Return type: function
+
+
+
+
+
+
+
+The windows.native_exec also contains some submodules:
+
+
+
+
+
+
+
+class windows.native_exec.cpuid.X86CpuidResult[source]
+Raw result of the CPUID instruction
+
+
+fields = ['EAX', 'EBX', 'ECX', 'EDX']
+Fields of the Structure
+
+
+
+
+
+
+windows.native_exec.cpuid.do_cpuid( req ) [source]
+Performs a CPUID for the current process bitness
+
+
+
+
+
+windows.native_exec.cpuid.get_proc_family_model( ) [source]
+Extracts the family and model based on vendorId
+
+
+
+
+Return type: (ComputedFamily, ComputedModel)
+
+
+
+
+
+
+
+windows.native_exec.cpuid.get_vendor_id( ) [source]
+Extracts the VendorId string from CPUID
+
+
+
+
+Return type: str
+
+
+
+
+
+
+
+windows.native_exec.cpuid.is_amd_proc( ) [source]
+get_vendor_id() == ‘AuthenticAMD’
+
+
+
+
+windows.native_exec.cpuid.is_intel_proc( ) [source]
+get_vendor_id() == ‘GenuineIntel’
+
+
+
+
+windows.native_exec.cpuid.x64_cpuid( req ) [source]
+Performs a CPUID in 64bits mode
+
+
+
+
+
+windows.native_exec.cpuid.x86_cpuid( req ) [source]
+Performs a CPUID in 32bits mode
+
+
+
+
Demo:
+
>>> import windows.native_exec.cpuid
+>>> windows . native_exec . cpuid . do_cpuid ( 0 )
+<windows.native_exec.cpuid.X86CpuidResult object at 0x0330D990>
+>>> x = windows . native_exec . cpuid . do_cpuid ( 0 )
+>>> x . EAX
+13L
+>>> x . EBX
+1970169159L
+>>> windows . native_exec . cpuid . get_vendor_id ()
+'GenuineIntel'
+>>> windows . native_exec . cpuid . get_proc_family_model ()
+(6L, 58L)
+
+
+
+
+
+
The windows.native_exec.simple_x86 module allows to create simple x86 code.
+
+Its features are:
+
+Forward - Backward jump (using labels)
+Non-string interface for conditional/context dependent generation
+
+
+
+
+
Note
+
The assembler DOES NOT handle every instruction at all.
+
+
The assembler instructions are Python object that may accept arguments representing
+the mnemonic operands.
+
+These parameters can be of type:
+
+
+
+
+
+class windows.native_exec.simple_x86.mem_access( base , index , scale , disp , prefix )
+
+
+base
+Alias for field number 0
+
+
+
+
+disp
+Alias for field number 3
+
+
+
+
+index
+Alias for field number 1
+
+
+
+
+prefix
+Alias for field number 4
+
+
+
+
+scale
+Alias for field number 2
+
+
+
+
+
+The mem_access object can be created:
+
+
+
+
+
+windows.native_exec.simple_x86.create_displacement( base=None , index=None , scale=None , disp=0 , prefix=None ) [source]
+Creates a X86 memory access description
+
+
+
+
+windows.native_exec.simple_x86.deref( disp ) [source]
+Create a memory access for an immediate value Ex: [0x42424242]
+
+
+
+
+windows.native_exec.simple_x86.mem( data ) [source]
+Parse a memory access string of format [EXPR] or seg:[EXPR]
+EXPR may describe: BASE | INDEX * SCALE | DISPLACEMENT or any combinaison (in this order)
+
+
+
Instruction assembling:
+
>>> import windows.native_exec.simple_x86 as x86
+>>> import random
+>>> x86 . Mov
+<class 'windows.native_exec.simple_x86.Mov'>
+>>> instr = x86 . Mov ( "EAX" , "EBX" )
+>>> instr
+<windows.native_exec.simple_x86.Mov object at 0x03243770>
+>>> instr . get_code ()
+'\x89\xd8'
+>>> x86 . Mov ( "EAX" , 0x42424242 ) . get_code ()
+'\xc7\xc0BBBB'
+>>> x86 . Mov ( "EAX" , x86 . create_displacement ( base = "EAX" , disp = random . randint ( 0 , 0xffffffff ))) . get_code ()
+'\x8b\x80\x977\n&'
+>>> x86 . Mov ( x86 . mem ( "[EBX + EDI * 2 + 0x11111111]" ), "EAX" ) . get_code ()
+'\x89\x84{\x11\x11\x11\x11'
+>>> x86 . Mov ( x86 . mem ( "gs:[EBX + EDI * 2 + 0x11111111]" ), "EAX" ) . get_code ()
+'e\x89\x84{\x11\x11\x11\x11'
+
+
+
windows.native_exec.simple_x86 also provides an interface to complex shellcode assembling
+including jump and label via the MultipleInstr class.
+
Shellcode assembling:
+
import windows.native_exec.simple_x86 as x86
+
+code = x86 . MultipleInstr ()
+code += x86 . Label ( ":BEGIN" )
+code += x86 . Jmp ( ":BEGIN" )
+print ( repr ( code . get_code ()))
+# '\xeb\xfe'
+
+
+
Another example from a project:
+
IO_STACK_INPUT_BUFFER_LEN = x86 . mem ( '[ESI + 8]' )
+IO_STACK_INPUT_BUFFER = x86 . mem ( '[ESI + 0x10]' )
+
+INPUT_BUFFER_SIZE = x86 . mem ( '[ECX]' )
+INPUT_BUFFER_PORT = x86 . mem ( '[ECX + 4]' )
+INPUT_BUFFER_VALUE = x86 . mem ( '[ECX + 8]' )
+
+out_ioctl = x86 . MultipleInstr ()
+out_ioctl += x86 . Cmp ( IO_STACK_INPUT_BUFFER_LEN , 0xc ) # size indicator / port / value
+out_ioctl += x86 . Jnz ( ":FAIL" )
+out_ioctl += x86 . Mov ( 'ECX' , IO_STACK_INPUT_BUFFER )
+out_ioctl += x86 . Mov ( 'EDX' , INPUT_BUFFER_PORT )
+out_ioctl += x86 . Mov ( 'EAX' , INPUT_BUFFER_VALUE )
+out_ioctl += x86 . Mov ( 'ECX' , INPUT_BUFFER_SIZE )
+out_ioctl += x86 . Cmp ( 'ECX' , 0x1 )
+out_ioctl += x86 . Jnz ( ":OUT_2_OR_4" )
+out_ioctl += x86 . Out ( 'DX' , 'AL' )
+out_ioctl += x86 . Jmp ( ':SUCCESS' )
+out_ioctl += x86 . Label ( ":OUT_2_OR_4" )
+out_ioctl += x86 . Cmp ( 'ECX' , 0x2 )
+out_ioctl += x86 . Jnz ( ":OUT_4" )
+out_ioctl += x86 . Out ( 'DX' , 'AX' )
+out_ioctl += x86 . Jmp ( ':SUCCESS' )
+out_ioctl += x86 . Label ( ":OUT_4" )
+out_ioctl += x86 . Out ( 'DX' , 'EAX' )
+out_ioctl += x86 . Label ( ":SUCCESS" )
+out_ioctl += x86 . Xor ( 'EAX' , 'EAX' )
+out_ioctl += x86 . Ret ()
+out_ioctl += x86 . Label ( ":FAIL" )
+out_ioctl += x86 . Mov ( 'EAX' , 0x0C000000D )
+out_ioctl += x86 . Ret ()
+
+out_ioctl . get_code ()
+' \x81 ~ \x08\x0c\x00\x00\x00 u& \x8b N \x10\x8b Q \x04\x8b A \x08\x8b\t\x81\xf9\x01\x00\x00\x00 u \x03\xee\xeb\r\x81\xf9\x02\x00\x00\x00 u \x04 f \xef\xeb\x01\xef 1 \xc0\xc3\xc7\xc0\r\x00\x00\xc0\xc3 '
+
+
+
+
+
+
Same things as windows.native_exec.simple_x86
+
+The only things that change are:
+
+
+
+
windows.native_exec.simple_x64 handles 32 and 64 bits operations.
+
Demo:
+
>>> import windows.native_exec.simple_x64 as x64
+>>> x64 . Mov ( "RAX" , "R13" ) . get_code ()
+'L\x89\xe8'
+>>> x64 . Mov ( "EAX" , "EDI" ) . get_code ()
+'\x89\xf8'
+>>> x64 . Mov ( "RAX" , "EDI" ) . get_code ()
+"""
+ValueError: Size mismatch
+"""
+>>> x64 . Mov ( "RAX" , x64 . mem ( "[EAX]" )) . get_code ()
+'gH\x8b\x00'
+>>> x64 . Mov ( "RAX" , x64 . mem ( "[RAX]" )) . get_code ()
+'H\x8b\x00'
+>>> x64 . Mov ( "EAX" , x64 . mem ( "[RAX]" )) . get_code ()
+'\x8b\x00'
+>>> x64 . Mov ( "EAX" , x64 . mem ( "[EAX]" )) . get_code ()
+'g\x8b\x00'
+
+
+
+
+
+
This module contains some native-code functions that can be used for various purposes.
+Each function export a label that allow another MultipleInstr to call the code of the function.
+
The current functions are:
+
+
+StrlenW64 A 64bits wide-string STRLEN (Label(":FUNC_STRLENW64") )
+
+StrlenA64 A 64bits ASCII STRLEN (Label(":FUNC_STRLENA64") )
+
+GetProcAddress64 A 64bits export resolver (Label(":FUNC_GETPROCADDRESS64") )
+
+
+Arg1: The DLL (wstring)
+
+Arg2: The API (string)
+
+Return value:
+
+
+0xfffffffffffffffe if the DLL is not found
+0xffffffffffffffff if the API is not found
+The address of the function
+
+
+
+
+
+
+StrlenW32 A 32bits wide-string STRLEN (Label(":FUNC_STRLENW32") )
+
+StrlenA32 A 32bits ASCII STRLEN (Label(":FUNC_STRLENA32") )
+
+GetProcAddress32 A 32bits export resolver (Label(":FUNC_GETPROCADDRESS32") )
+
+
+Arg1: The DLL (wstring)
+
+Arg2: The API (string)
+
+Return value:
+
+
+0xfffffffe if the DLL is not found
+0xffffffff if the API is not found
+The address of the function
+
+
+
+
+
+
+
+
+
To use those functions in a MultipleInstr just call the label in your code and append the function at
+the end of your MultipleInstr
+
Example:
+
RemoteManualLoadLibray = x86 . MultipleInstr ()
+
+RemoteManualLoadLibray += x86 . Mov ( "ECX" , x86 . mem ( "[ESP + 4]" ))
+RemoteManualLoadLibray += x86 . Push ( x86 . mem ( "[ECX + 4]" ))
+RemoteManualLoadLibray += x86 . Push ( x86 . mem ( "[ECX]" ))
+RemoteManualLoadLibray += x86 . Call ( ":FUNC_GETPROCADDRESS32" )
+RemoteManualLoadLibray += x86 . Push ( x86 . mem ( "[ECX + 8]" ))
+RemoteManualLoadLibray += x86 . Call ( "EAX" ) # LoadLibrary
+RemoteManualLoadLibray += x86 . Pop ( "ECX" )
+RemoteManualLoadLibray += x86 . Pop ( "ECX" )
+RemoteManualLoadLibray += x86 . Ret ()
+
+RemoteManualLoadLibray += GetProcAddress32
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/network.html b/docs/build/html/network.html
new file mode 100644
index 0000000..3a8817e
--- /dev/null
+++ b/docs/build/html/network.html
@@ -0,0 +1,621 @@
+
+
+
+
+
+
+
+ 2.6. Network — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2.6. Network
+
+
+
+class windows.winobject.network.Network[source]
+
+
+firewall
+The firewall of the system
+
+
+
+
+
+ipv4
+List of TCP IPv4 socket (connection and listening)
+
+
+
+
+
+ipv6
+List of TCP IPv6 socket (connection and listening)
+
+
+
+
+
+
+
2.6.1. Connections
+
+
+class windows.winobject.network.TCP4Connection[source]
+A TCP4 socket (connected or listening)
+
+
+close( ) [source]
+Close the connection <require elevated process>
+
+
+
+
+established
+True if connection is established else it’s a listening socket
+
+
+
+
+local_addr
+Local address IP (x.x.x.x)
+
+
+
+
+
+local_port
+
+
+
+
+
+remote_addr
+remote address IP (x.x.x.x)
+
+
+
+
+
+remote_host
+Identification of the remote hostname.
+Equals remote_addr if the resolution fails
+
+
+
+
+
+remote_port
+
+
+
+
+
+remote_proto
+Identification of the protocol associated with the remote port.
+Equals remote_port if no protocol is associated with it.
+
+
+
+
+
+
+
+class windows.winobject.network.TCP6Connection[source]
+A TCP6 socket (connected or listening)
+
+
+established
+True if connection is established else it’s a listening socket
+
+
+
+
+local_addr
+Local address IP
+
+
+
+
+
+local_port
+
+
+
+
+
+remote_addr
+remote address IP
+
+
+
+
+
+remote_host
+Equals to self.remote_addr for Ipv6
+
+
+
+
+remote_port
+
+
+
+
+
+remote_proto
+Equals to self.remote_port for Ipv6
+
+
+
+
+
+
+
2.6.2. Firewall
+
+
+class windows.winobject.network.Firewall[source]
+The windows firewall
+
+
+current_profile_types
+Mask of the profiles currently enabled
+
+
+
+
+
+enabled
+A maping of the active firewall profiles
+{
+NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_DOMAIN(0x1L) : True or False ,
+NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PRIVATE(0x2L) : True or False ,
+NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_PUBLIC(0x4L) : True or False ,
+}
+
+
+
+
+
+rules
+The rules of the firewall
+
+
+
+
+
+value
+current value
+
+
+
+
+
+
+class windows.winobject.network.FirewallRule[source]
+A rule of the firewall
+
+
+action
+Action of the rule, values might be:
+
+
+NET_FW_ACTION_.NET_FW_ACTION_BLOCK(0x0L)
+NET_FW_ACTION_.NET_FW_ACTION_ALLOW(0x1L)
+
+
+subclass of long
+
+
+
+
+application_name
+Name of the application to which apply the rule
+
+
+
+
+Type: unicode
+
+
+
+
+
+
+
+description
+Description of the rule
+
+
+
+
+Type: unicode
+
+
+
+
+
+
+
+direction
+Direction of the rule, values might be:
+
+
+NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN(0x1L)
+NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_OUT(0x2L)
+
+
+subclass of long
+
+
+
+
+enabled
+True if rule is enabled
+
+
+
+
+grouping
+Grouping of the rule
+
+
+
+
+Type: unicode
+
+
+
+
+
+
+
+interface_types
+Types of interface of the rule
+
+
+
+
+Type: unicode
+
+
+
+
+
+
+
+local_address
+Local address of the rule
+
+
+
+
+Type: unicode
+
+
+
+
+
+
+
+local_port
+Local port of the rule
+
+
+
+
+Type: unicode
+
+
+
+
+
+
+
+name
+Name of the rule
+
+
+
+
+Type: unicode
+
+
+
+
+
+
+
+protocol
+Protocol to which apply the rule
+
+
+
+
+
+remote_address
+Remote address of the rule
+
+
+
+
+Type: unicode
+
+
+
+
+
+
+
+remote_port
+Remote port of the rule
+
+
+
+
+Type: unicode
+
+
+
+
+
+
+
+service_name
+Name of the service to which apply the rule
+
+
+
+
+Type: unicode
+
+
+
+
+
+
+
+value
+current value
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/process.html b/docs/build/html/process.html
new file mode 100644
index 0000000..7ac2288
--- /dev/null
+++ b/docs/build/html/process.html
@@ -0,0 +1,1703 @@
+
+
+
+
+
+
+
+ 2.1. Processes and Threads — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2.1. Processes and Threads
+
+
2.1.1. CurrentProcess
+
+
+
+class windows.winobject.process.CurrentProcess[source]
+Bases: windows.winobject.process.Process
+The current process
+
+
+allocated_memory( *args , **kwds )
+ContextManager to allocate memory and free it
+
+
+
+
+Type: int – the address of the allocated memory
+
+
+
+
+
+
+
+bitness
+The bitness of the process
+
+
+
+
+Type: int – 32 or 64
+
+
+
+
+
+
+
+create_thread( lpStartAddress , lpParameter , dwCreationFlags=0 ) [source]
+Create a new thread
+
+
+
+
+
+execute( code , parameter=0 ) [source]
+Execute native code code in the current thread.
+
+
+
+
+Return type: int the return value of the native code
+
+
+
+
+
+
+
+exit( code=0 ) [source]
+Exit the process
+
+
+
+
+exit_code
+The exit code of the process : STILL_ACTIVE means the process is not dead
+
+
+
+
+
+get_mapped_filename( addr )
+The filename mapped at address addr or None
+
+
+
+
+Return type: str or None
+
+
+
+
+
+
+
+handle
+An handle on the object
+
+
+
+
+Type: HANDLE
+
+
Note
+
The handle is automaticaly closed when the object is destroyed
+
+
+
+
+
+
+
+
+
+is_exit
+True if the process is terminated
+
+
+
+
+
+is_wow_64
+True if the process is a SysWow64 process (32bit process on 64bits system).
+
+
+
+
+
+memory_state( )
+Yield the memory information for the whole address space of the process
+
+
+
+
+Yield: MEMORY_BASIC_INFORMATION
+
+
+
+
+
+
+
+peb
+The Process Environment Block of the current process
+
+
+
+
+
+peb_syswow
+The 64bits PEB of a SysWow64 process
+
+
+
+
+
+pid
+Process ID
+
+
+
+
+
+ppid
+Parent Process ID
+
+
+
+
+
+query_memory( addr )
+Query the memory informations about page at addr
+
+
+
+
+Return type: MEMORY_BASIC_INFORMATION
+
+
+
+
+
+
+
+read_byte( addr )
+Read a CHAR at addr
+
+
+
+
+read_dword( addr )
+Read a DWORD at addr
+
+
+
+
+read_memory( addr , size ) [source]
+Read size from addr
+
+
+
+
+Returns: The data read
+
+Return type: str
+
+
+
+
+
+
+
+read_ptr( addr )
+Read a PTR at addr
+
+
+
+
+read_qword( addr )
+Read a ULONG64 at addr
+
+
+
+
+read_short( addr )
+Read a SHORT at addr
+
+
+
+
+read_string( addr )
+Read an ascii string at addr
+
+
+
+
+read_wstring( addr )
+Read a windows UTF16 string at addr
+
+
+
+
+threads
+The threads of the process
+
+
+
+
+Type: [WinThread ] – A list of Thread
+
+
+
+
+
+
+
+time_info
+The time information of the process (creation, kernel/user time, exit time)
+
+
+
+
+Type: TimeInfo
+
+
+
+
+
+
+
+token
+The token of the process
+
+
+
+
+
+virtual_alloc( size , prot=PAGE_EXECUTE_READWRITE(0x40L) ) [source]
+Allocate memory in the process
+
+
+
+
+Returns: The address of the allocated memory
+
+Return type: int
+
+
+
+
+
+
+
+virtual_free( addr ) [source]
+Free memory in the process by virtual_alloc
+
+
+
+
+virtual_protect( addr , size , protect , old_protect )
+Change the access right of one or more page of the process
+
+
+
+
+virtual_protected( *args , **kwds )
+A context manager for local virtual_protect (old Protection are restored at exit)
+
+
+
+
+wait( timeout=INFINITE(0xffffffffL) ) [source]
+Raise ValueError to prevent deadlock :D
+
+
+
+
+write_byte( addr , byte )
+write a byte at addr
+
+
+
+
+write_dword( addr , dword )
+write a dword at addr
+
+
+
+
+write_memory( addr , data ) [source]
+Write data at addr
+
+
+
+
+write_qword( addr , qword )
+write a qword at addr
+
+
+
+
+write_short( addr , word )
+write a word at addr
+
+
+
+
+
+
+
2.1.2. CurrentThread
+
+
+class windows.winobject.process.CurrentThread[source]
+Bases: windows.winobject.process.AutoHandle
+The current thread
+
+
+exit( code=0 ) [source]
+Exit the thread
+
+
+
+
+handle
+An handle on the object
+
+
+
+
+Type: HANDLE
+
+
Note
+
The handle is automaticaly closed when the object is destroyed
+
+
+
+
+
+
+
+
+
+owner
+The current process
+
+
+
+
+
+tid
+Thread ID
+
+
+
+
+
+wait( timeout=INFINITE(0xffffffffL) ) [source]
+Raise ValueError to prevent deadlock :D
+
+
+
+
+
+
+
2.1.3. WinProcess
+
+
+
+class windows.winobject.process.WinProcess( pid=None , handle=None , name=None , ppid=None ) [source]
+Bases: windows.winobject.process.Process
+A Process on the system
+
+
+allocated_memory( *args , **kwds )
+ContextManager to allocate memory and free it
+
+
+
+
+Type: int – the address of the allocated memory
+
+
+
+
+
+
+
+bitness
+The bitness of the process
+
+
+
+
+Returns: int – 32 or 64
+
+
+
+
+
+
+
+create_thread( addr , param ) [source]
+Create a remote thread
+
+
+
+
+
+execute( code , parameter=0 )
+Execute some native code in the context of the process
+
+
+
+
+
+execute_python( pycode ) [source]
+Execute Python code into the remote process.
+This function waits for the remote process to end and
+raises an exception if the remote thread raised one
+
+
+
+
+execute_python_unsafe( pycode ) [source]
+Execute Python code into the remote process.
+
+
+
+
+Return type:
+
+
+
+
+
+
+
+
+exit( code=0 ) [source]
+Exit the process
+
+
+
+
+exit_code
+The exit code of the process : STILL_ACTIVE means the process is not dead
+
+
+
+
+
+get_mapped_filename( addr )
+The filename mapped at address addr or None
+
+
+
+
+Return type: str or None
+
+
+
+
+
+
+
+handle
+An handle on the object
+
+
+
+
+Type: HANDLE
+
+
Note
+
The handle is automaticaly closed when the object is destroyed
+
+
+
+
+
+
+
+
+
+is_exit
+True if the process is terminated
+
+
+
+
+
+is_wow_64
+True if the process is a SysWow64 process (32bit process on 64bits system).
+
+
+
+
+
+load_library( dll_path ) [source]
+Load the library in remote process
+
+
+
+
+memory_state( )
+Yield the memory information for the whole address space of the process
+
+
+
+
+Yield: MEMORY_BASIC_INFORMATION
+
+
+
+
+
+
+
+name
+Name of the process
+
+
+
+
+
+peb
+The PEB of the process (see remotectypes )
+
+
+
+
+
+peb_addr
+The address of the PEB
+
+
+
+
+
+peb_syswow
+The 64bits PEB of a SysWow64 process
+
+
+
+
+
+pid
+Process ID
+
+
+
+
+
+ppid
+Parent Process ID
+
+
+
+
+
+query_memory( addr )
+Query the memory informations about page at addr
+
+
+
+
+Return type: MEMORY_BASIC_INFORMATION
+
+
+
+
+
+
+
+read_byte( addr )
+Read a CHAR at addr
+
+
+
+
+read_dword( addr )
+Read a DWORD at addr
+
+
+
+
+read_memory( addr , size ) [source]
+Read size from addr
+
+
+
+
+Returns: The data read
+
+Return type: str
+
+
+
+
+
+
+
+read_memory_into( addr , struct ) [source]
+Read a ctypes struct from addr
+
+
+
+
+Returns: struct
+
+
+
+
+
+
+
+read_ptr( addr )
+Read a PTR at addr
+
+
+
+
+read_qword( addr )
+Read a ULONG64 at addr
+
+
+
+
+read_short( addr )
+Read a SHORT at addr
+
+
+
+
+read_string( addr )
+Read an ascii string at addr
+
+
+
+
+read_wstring( addr )
+Read a windows UTF16 string at addr
+
+
+
+
+threads
+The threads of the process
+
+
+
+
+Type: [WinThread ] – A list of Thread
+
+
+
+
+
+
+
+time_info
+The time information of the process (creation, kernel/user time, exit time)
+
+
+
+
+Type: TimeInfo
+
+
+
+
+
+
+
+token
+The token of the process
+
+
+
+
+
+virtual_alloc( size , prot=PAGE_EXECUTE_READWRITE(0x40L) ) [source]
+Allocate memory in the process
+
+
+
+
+Returns: The address of the allocated memory
+
+Return type: int
+
+
+
+
+
+
+
+virtual_free( addr ) [source]
+Free memory in the process by virtual_alloc
+
+
+
+
+virtual_protect( addr , size , protect , old_protect )
+Change the access right of one or more page of the process
+
+
+
+
+virtual_protected( *args , **kwds )
+A context manager for local virtual_protect (old Protection are restored at exit)
+
+
+
+
+wait( timeout=INFINITE(0xffffffffL) )
+Wait for the object
+
+
+
+
+write_byte( addr , byte )
+write a byte at addr
+
+
+
+
+write_dword( addr , dword )
+write a dword at addr
+
+
+
+
+write_memory( addr , data ) [source]
+Write data at addr
+
+
+
+
+write_qword( addr , qword )
+write a qword at addr
+
+
+
+
+write_short( addr , word )
+write a word at addr
+
+
+
+
+
+
+
2.1.4. WinThread
+
+
+class windows.winobject.process.WinThread[source]
+Bases: windows.generated_def.winstructs.tagTHREADENTRY32 , windows.winobject.process.AutoHandle
+Represent a thread
+
+
+context
+The context of the thread, type depend of the target process.
+
+
+
+
+Type: windows.exception.ECONTEXT32 or windows.exception.ECONTEXT64 or windows.exception.ECONTEXTWOW64
+
+
+
+
+
+
+
+context_syswow
+The 64 bits context of a syswow thread.
+
+
+
+
+Type: windows.exception.ECONTEXT64
+
+
+
+
+
+
+
+exit( code=0 ) [source]
+Exit the thread
+
+
+
+
+exit_code
+The exit code of the thread : STILL_ACTIVE means the process is not dead
+
+
+
+
+
+handle
+An handle on the object
+
+
+
+
+Type: HANDLE
+
+
Note
+
The handle is automaticaly closed when the object is destroyed
+
+
+
+
+
+
+
+
+
+is_exit
+True if the thread is terminated
+
+
+
+
+
+owner
+The Process owning the thread
+
+
+
+
+
+resume( ) [source]
+Resume the thread
+
+
+
+
+set_context( context ) [source]
+Set the thread’s context to context
+
+
+
+
+set_syswow_context( context ) [source]
+Set a syswow thread’s 64 context to context
+
+
+
+
+start_address
+The start address of the thread
+
+
+
+
+
+suspend( ) [source]
+Suspend the thread
+
+
+
+
+teb_base
+The address of the thread’s TEB
+
+
+
+
+
+tid
+Thread ID
+
+
+
+
+
+wait( timeout=INFINITE(0xffffffffL) )
+Wait for the object
+
+
+
+
+
+
+class windows.winobject.process.DeadThread( handle , tid=None ) [source]
+Bases: windows.winobject.process.AutoHandle
+An already dead thread (returned only by API returning a new thread if thread die before being returned)
+
+
+exit_code
+The exit code of the thread : STILL_ACTIVE means the process is not dead
+
+
+
+
+
+handle
+An handle on the object
+
+
+
+
+Type: HANDLE
+
+
Note
+
The handle is automaticaly closed when the object is destroyed
+
+
+
+
+
+
+
+
+
+is_exit
+True if the thread is terminated
+
+
+
+
+
+wait( timeout=INFINITE(0xffffffffL) )
+Wait for the object
+
+
+
+
+
+
+
2.1.5. Token
+
+
+class windows.winobject.process.Token( handle ) [source]
+The token of a process
+
+
+computername
+The computername of the token
+
+
+
+
+handle
+An handle on the object
+
+
+
+
+Type: HANDLE
+
+
Note
+
The handle is automaticaly closed when the object is destroyed
+
+
+
+
+
+
+
+
+
+integrity
+Return the integrity level of a process
+
+
+
+
+
+is_elevated
+True if process is Admin
+
+
+
+
+username
+The username of the token
+
+
+
+
+wait( timeout=INFINITE(0xffffffffL) )
+Wait for the object
+
+
+
+
+
+
+
+
2.2. PEB Exploration
+
The windows module is able to parse the PEB of the current process or remote process.
+The PEB is accessible via process.peb and is of type PEB .
+
+
+
2.2.1. PEB
+
+
+class windows.winobject.process.PEB[source]
+The PEB (Process Environment Block) of the current process
+
+
+commandline
+The CommandLine of the PEB
+
+
+
+
+
+imagepath
+The ImagePathName of the PEB
+
+
+
+
+
+modules
+The loaded modules present in the PEB
+
+
+
+
+
+
+
+class windows.winobject.process.WinUnicodeString[source]
+LSA_UNICODE_STRING with a nice __repr__
+
+
+fields = ['Length', 'MaximumLength', 'Buffer']
+The fields of the structure
+
+
+
+
+str
+The python string of the LSA_UNICODE_STRING object
+
+
+
+
+Type: unicode
+
+
+
+
+
+
+
+
+
+
2.2.2. LoadedModule
+
+
+class windows.winobject.process.LoadedModule[source]
+
+
+baseaddr
+Base address of the module
+
+
+
+
+
+fullname
+Full name of the module (path)
+
+
+
+
+
+name
+Name of the module
+
+
+
+
+
+pe
+A PE representation of the module
+
+
+
+
+
+
+
+
+
2.3. PEFile - Parsing loaded PE
+
+
+
+
+windows.pe_parse.GetPEFile( baseaddr , target=None , force_bitness=None ) [source]
+Returns a PEFile to explore a PE loaded at baseaddr in process target .
+
+
+
+
+Return type: PEFile
+
+
+
+
+
Note
+
If target is None it refers to the curent process
+
+
+
+
+
2.3.1.1. PEFile
+
+
+class windows.pe_parse.PEFile
+Represent a PE loaded in a process (current or remote)
+
+
+export_name
+The Name attribute of the EXPORT_DIRECTORY
+
+
+
+
+exports
+The exports of the PE in a dict. Keys are ordinal (int ) and name (str ).
+The values are the addresses of the exports.
+
+
+
+
+
+
+imports
+The imports of the PE in a dict.
+Keys are the names of DLL to import from and values are list
+of IATEntry
+
+
+
+
+
+
+
+
+
2.3.1.2. IATEntry
+
+
+class windows.pe_parse.IATEntry
+Represent an entry in the IAT of a module
+Can be used to get resolved value and setup hook
+
+
+addr
+int : Address of the IAT Entry
+
+
+
+
+ord
+int : Ordinal of the imported function
+
+
+
+
+name
+int : Name of the imported function
+
+
+
+
+value
+int : The content (destination) of the IAT entry
+
+
Warning
+
value is a descriptor. Setting its value will actually CHANGE THE IAT ENTRY, resulting in a segfault if no VirtualProtect have been done.
+
+
+
+
+
+
+remove_hook( )
+Remove the hook on the entry
+
+
+
+
+set_hook( callback , types=None )
+Setup a hook on the entry and return it.
+You MUST keep a reference to the hook while the hook is enabled.
+
+
+
Warning
+
This works only for PEFile with the current process as target.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/py-modindex.html b/docs/build/html/py-modindex.html
new file mode 100644
index 0000000..27c6c45
--- /dev/null
+++ b/docs/build/html/py-modindex.html
@@ -0,0 +1,216 @@
+
+
+
+
+
+
+
+ Python Module Index — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Python Module Index
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/registry.html b/docs/build/html/registry.html
new file mode 100644
index 0000000..6c3c4c2
--- /dev/null
+++ b/docs/build/html/registry.html
@@ -0,0 +1,257 @@
+
+
+
+
+
+
+
+ 2.5. Registry — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2.5. Registry
+
+
+
2.5.1. Registry
+
+
+class windows.winobject.registry.Registry[source]
+The Windows registry: a read only (for now) mapping
+
+
+
+
+
2.5.2. PyHKey
+
+
+class windows.winobject.registry.PyHKey( surkey , name , sam=KEY_READ(0x20019L) ) [source]
+A windows registry key
+
+
+__call__( name )
+Alias for open_subkey()
+
+
+
+
+__getitem__( name )
+Alias for get()
+
+
+
+
+__setitem__( name ) [source]
+Wrapper for set() , accept value or (value, type)
+
+
+
+
+get( value_name ) [source]
+Retrieves the value value_name
+
+
+
+
+
+open_subkey( name , sam=None ) [source]
+Open the subkey name
+
+
+
+
+Return type: PyHKey
+
+
+
+
+
+
+
+set( name , value , type=None ) [source]
+Set the value for name to value . if type is None try to guess items
+
+
+
+
+subkeys
+The subkeys of the registry key
+
+
+
+
+Type: [PyHKey ] - A list of keys
+
+
+
+
+
+
+
+values
+The values of the registry key
+
+
+
+
+Type: [KeyValue ] - A list of values
+
+
+
+
+
+
+
+
+
+
2.5.3. KeyValue
+
+
+class windows.winobject.registry.KeyValue( name , value , type )
+A registry value (name, value, type)
+
+
+name
+Alias for field number 0
+
+
+
+
+type
+Alias for field number 2
+
+
+
+
+value
+Alias for field number 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/sample.html b/docs/build/html/sample.html
new file mode 100644
index 0000000..90aa20c
--- /dev/null
+++ b/docs/build/html/sample.html
@@ -0,0 +1,1407 @@
+
+
+
+
+
+
+
+ 12. Samples of code — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
12. Samples of code
+
+
12.1. windows.current_process
+
import sys
+import os.path
+sys . path . append ( os . path . abspath ( __file__ + "\..\.." ))
+
+import windows
+import windows.native_exec.simple_x86 as x86
+import windows.native_exec.simple_x64 as x64
+# Here is our current process
+cp = windows . current_process
+
+print ( "current process is {cp} " . format ( cp = windows . current_process ))
+print ( "current process is a < {cp.bitness} > bits process" . format ( cp = cp ))
+print ( "current process is a SysWow64 process ? < {cp.is_wow_64} >" . format ( cp = cp ))
+print ( "current process pid < {cp.pid} > and ppid < {cp.ppid} >" . format ( cp = cp ))
+print ( "Here are the current process threads: < {cp.threads} >" . format ( cp = cp ))
+
+print ( "Let's execute some native code ! (0x41 + 1)" )
+
+if windows . current_process . bitness == 32 :
+ # Let's generate some native code
+ code = x86 . MultipleInstr ()
+ code += x86 . Mov ( "Eax" , 0x41 )
+ code += x86 . Inc ( "EAX" )
+ code += x86 . Ret ()
+else :
+ code = x64 . MultipleInstr ()
+ code += x64 . Mov ( "RAX" , 0x41 )
+ code += x64 . Inc ( "RAX" )
+ code += x64 . Ret ()
+
+native_code = code . get_code ()
+
+v = windows . current_process . execute ( native_code )
+print ( "Native code returned < {0} >" . format ( hex ( v )))
+
+print ( "Allocating memory in current process" )
+addr = cp . virtual_alloc ( 0x1000 ) # Default alloc is RWX (so secure !)
+print ( "Allocated memory is at < {0} >" . format ( hex ( addr )))
+
+print ( "Writing 'SOME STUFF' in allocation memory" )
+cp . write_memory ( addr , "SOME STUFF" )
+print ( "Reading memory : < {0} >" . format ( repr ( cp . read_memory ( addr , 20 ))))
+
+
+
+
+
Output:
+
(cmd λ) python32.exe current_process.py
+current process is <windows.winobject.process.CurrentProcess object at 0x030A2590>
+current process is a <32> bits process
+current process is a SysWow64 process ? <True>
+current process pid <8264> and ppid <4100>
+Here are the current process threads: <[<WinThread 13540 owner "python.exe" at 0x32d3210>]>
+Let's execute some native code ! (0x41 + 1)
+Native code returned <0x42>
+Allocating memory in current process
+Allocated memory is at <0xd60000>
+Writing 'SOME STUFF' in allocation memory
+Reading memory : <'SOME STUFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'>
+
+
+
+
+
12.2. Remote process : WinProcess
+
import sys
+import os.path
+sys . path . append ( os . path . abspath ( __file__ + "\..\.." ))
+
+import windows
+import windows.native_exec.simple_x86 as x86
+import windows.native_exec.simple_x64 as x64
+
+print ( "Creating a calc" )
+calc = windows . utils . create_process ( r"C:\windows\system32\calc.exe" )
+# You don't need to do that in our case, but it's useful to now
+print ( "Looking for calcs in the processes" )
+all_calcs = [ proc for proc in windows . system . processes if proc . name == "calc.exe" ]
+print ( "They are currently < {0} > calcs running on the system" . format ( len ( all_calcs )))
+
+print ( "Let's play with our calc: < {calc} >" . format ( calc = calc ))
+print ( "Our calc pid is {calc.pid} " . format ( calc = calc ))
+print ( "Our calc is a < {calc.bitness} > bits process" . format ( calc = calc ))
+print ( "Our calc is a SysWow64 process ? < {calc.is_wow_64} >" . format ( calc = calc ))
+print ( "Our calc have threads ! < {calc.threads} >" . format ( calc = calc ))
+
+# PEB STUFF
+peb = calc . peb
+print ( "Exploring our calc PEB ! {peb} " . format ( peb = peb ))
+print ( "Command line is {peb.commandline} " . format ( peb = peb ))
+modules = peb . modules
+print ( "Here are 3 loaded modules: {0} " . format ( modules [: 3 ]))
+# See iat_hook.py for module exploration
+
+
+# Remote alloc / read / write
+
+print ( "Allocating memory in our calc" )
+addr = calc . virtual_alloc ( 0x1000 )
+print ( "Allocated memory is at < {0} >" . format ( hex ( addr )))
+print ( "Writing 'SOME STUFF' in allocated memory" )
+calc . write_memory ( addr , "SOME STUFF" )
+print ( "Reading allocated memory : < {0} >" . format ( repr ( calc . read_memory ( addr , 20 ))))
+
+
+# Remote Execution
+
+print ( "Execution some native code in our calc (write 0x424242 at allocated address + return 0x1337)" )
+
+if calc . bitness == 32 :
+ # Let's generate some native code
+ code = x86 . MultipleInstr ()
+ code += x86 . Mov ( x86 . deref ( addr ), 0x42424242 )
+ code += x86 . Mov ( "EAX" , 0x1337 )
+ code += x86 . Ret ()
+else :
+ code = x64 . MultipleInstr ()
+ code += x64 . Mov ( 'RAX' , addr )
+ code += x64 . Mov ( x64 . mem ( "[RAX]" ), 0x42424242 )
+ code += x64 . Mov ( "RAX" , 0x1337 )
+ code += x64 . Ret ()
+
+print ( "Executing native code !" )
+t = calc . execute ( code . get_code ())
+t . wait ()
+print ( "Return code = {0} " . format ( hex ( t . exit_code )))
+print ( "Reading allocated memory : < {0} >" . format ( repr ( calc . read_memory ( addr , 20 ))))
+
+print ( "Executing python code !" )
+# Make 'windows' importable in remote python
+calc . execute_python ( "import sys; sys.path.append(r' {0} ')" . format ( sys . path [ - 1 ]))
+
+calc . execute_python ( "import windows" )
+# Let's write in the calc 'current_process' memory :)
+calc . execute_python ( "addr = {addr} ; windows.current_process.write_memory(addr, 'HELLO FROM CALC')" . format ( addr = addr ))
+print ( "Reading allocated memory : < {0} >" . format ( repr ( calc . read_memory ( addr , 20 ))))
+
+# python_execute is 'safe':
+# - it waits for the thread completion
+# - it raise an error if remote code raised some
+
+try :
+ print ( "Trying to import in remote module 'FAKE_MODULE'" )
+ calc . execute_python ( "def func(): \n import FAKE_MODULE \n func()" )
+except windows . injection . RemotePythonError as e :
+ print ( "Remote ERROR !" )
+ print ( e )
+
+print ( "That's all ! killing the calc" )
+calc . exit ()
+
+
+
+
+
+
+
+
+
+
Output:
+
(cmd λ) python.exe remote_calc.py
+Creating a calc
+Looking for calcs in the processes
+They are currently <1> calcs running on the system
+Let's play with our calc: <<WinProcess "calc.exe" pid 8052 at 0x27bd5d0>>
+Our calc pid is 8052
+Our calc is a <32> bits process
+Our calc is a SysWow64 process ? <True>
+Our calc have threads ! <[<WinThread 8552 owner "calc.exe" at 0x27f7f30>, <WinThread 3464 owner "calc.exe" at 0x27f7f80>, <WinThread 3840 owner "calc.exe" at 0x27fa030>]>
+Exploring our calc PEB ! <windows.winobject.RemotePEB object at 0x026DDD00>
+Command line is <RemoteWinUnicodeString ""C:\windows\system32\calc.exe"" at 0x26ddee0>
+Here are 3 loaded modules: [<RemoteLoadedModule "calc.exe" at 0x26dde40>, <RemoteLoadedModule "ntdll.dll" at 0x26ddf30>, <RemoteLoadedModule "kernel32.dll" at 0x26ddc60>]
+Allocating memory in our calc
+Allocated memory is at <0x5c90000>
+Writing 'SOME STUFF' in allocated memory
+Reading allocated memory : <'SOME STUFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'>
+Execution some native code in our calc (write 0x424242 at allocated address + return 0x1337
+Executing native code !
+Return code = 0x1337L
+Reading allocated memory : <'BBBB STUFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'>
+Executing python code !
+Reading allocated memory : <'HELLO FROM CALC\x00\x00\x00\x00\x00'>
+Trying to import in remote module 'FAKE_MODULE'
+Remote ERROR !
+Traceback (most recent call last):
+File "<string>", line 3, in <module>
+File "<string>", line 2, in func
+ImportError: No module named FAKE_MODULE
+
+That's all ! killing the calc
+
+
+
+
+
12.3. PEB exploration
+
import sys
+import os.path
+sys . path . append ( os . path . abspath ( __file__ + "\..\.." ))
+
+import windows
+
+print ( "Exploring the current process PEB" )
+peb = windows . current_process . peb
+print ( "PEB is < {0} >" . format ( peb ))
+commandline = peb . commandline
+print ( "Commandline object is {0} " . format ( commandline ))
+print ( "Commandline string is {0} " . format ( repr ( commandline . Buffer )))
+
+imagepath = peb . imagepath
+print ( "Imagepath {0} " . format ( imagepath ))
+
+modules = peb . modules
+print ( "Printing some modules: {0} " . format ( " \n " . join ( str ( m ) for m in modules [: 6 ])))
+
+print ( "=== K32 ===" )
+print ( "Looking for kernel32.dll" )
+k32 = [ m for m in modules if m . name == "kernel32.dll" ][ 0 ]
+print ( "Kernel32 module: {0} " . format ( k32 ))
+
+print ( "Module name = < {0} > | Fullname = < {1} >" . format ( k32 . name , k32 . fullname ))
+print ( "Kernel32 is loaded at address {0} " . format ( hex ( k32 . baseaddr )))
+
+print ( "=== K32 PE ===" )
+k32pe = k32 . pe
+print ( "PE Representation of k32: {0} " . format ( k32pe ))
+exports = k32pe . exports
+some_exports = dict (( k , v ) for k , v in exports . items () if k in [ 0 , 42 , "VirtualAlloc" , "CreateFileA" ])
+print ( "Here are some exports {0} " . format ( some_exports ))
+
+imports = k32pe . imports
+print ( "Import DLL dependancies are (without api-*): {0} " . format ([ x for x in imports . keys () if not x . startswith ( "api-" )]))
+
+NtCreateFile_iat = [ x for x in imports [ "ntdll.dll" ] if x . name == "NtCreateFile" ][ 0 ]
+print ( "IAT Entry for ntdll!NtCreateFile = {0} | addr = {1} " . format ( NtCreateFile_iat , hex ( NtCreateFile_iat . addr )))
+print ( "Sections: {0} " . format ( k32pe . sections ))
+
+
+
Output:
+
(cmd λ) python.exe peb.py
+Exploring the current process PEB
+PEB is <<windows.winobject.PEB object at 0x02649B70>>
+Commandline object is <WinUnicodeString "python.exe peb.py " at 0x2649c60>
+Commandline string is u'python.exe peb.py '
+Imagepath <WinUnicodeString "C:\Python27\python.exe" at 0x2649d50>
+Printing some modules: <LoadedModule "python.exe" at 0x272a030>
+<LoadedModule "ntdll.dll" at 0x272a080>
+<LoadedModule "kernel32.dll" at 0x272acb0>
+<LoadedModule "kernelbase.dll" at 0x272ad00>
+<LoadedModule "python27.dll" at 0x272ad50>
+<LoadedModule "msvcr90.dll" at 0x272ada0>
+=== K32 ===
+Looking for kernel32.dll
+Kernel32 module: <LoadedModule "kernel32.dll" at 0x272acb0>
+Module name = <kernel32.dll> | Fullname = <C:\Windows\SYSTEM32\KERNEL32.DLL>
+Kernel32 is loaded at address 0x774c0000
+=== K32 PE ===
+PE Representation of k32: <windows.pe_parse.PEFile object at 0x0272D350>
+Here are some exports {0: 2001566688L, u'CreateFileA': 2001635616L, 42: 2001647872L, u'VirtualAlloc': 2001570704L}
+Import DLL dependancies are (without api-*): [u'ntdll.dll', u'kernelbase.dll']
+IAT Entry for ntdll!NtCreateFile = <IATEntry "NtCreateFile" ordinal 253> | addr = 0x77541128L
+Sections: [<PESection ".text">, <PESection ".rdata">, <PESection ".data">, <PESection ".rsrc">, <PESection ".reloc">]
+
+
+
+
+
12.4. windows.system
+
import sys
+import os.path
+sys . path . append ( os . path . abspath ( __file__ + "\..\.." ))
+
+import windows
+system = windows . system
+
+print ( "Basic system infos:" )
+print ( " version = {0} " . format ( system . version ))
+print ( " bitness = {0} " . format ( system . bitness ))
+print ( " computer_name = {0} " . format ( system . computer_name ))
+print ( " product_type = {0} " . format ( system . product_type ))
+print ( " version_name = {0} " . format ( system . version_name ))
+print ( "" )
+print ( "There is {0} processes" . format ( len ( system . processes )))
+print ( "There is {0} threads" . format ( len ( system . threads )))
+print ( "" )
+
+print ( "Dumping first logical drive:" )
+drive = system . logicaldrives [ 0 ]
+print ( " " + str ( drive ))
+print (( " " * 8 ) + "name = {0} " . format ( drive . name ))
+print (( " " * 8 ) + "type = {0} " . format ( drive . type ))
+print (( " " * 8 ) + "path = {0} " . format ( drive . path ))
+print ( "" )
+
+print ( "Dumping first service:" )
+serv = windows . system . services [ 0 ]
+print ( " " + str ( serv ))
+print (( " " * 8 ) + "name = {0} " . format ( serv . name ))
+print (( " " * 8 ) + "description = {0} " . format ( serv . description ))
+print (( " " * 8 ) + "status = {0} " . format ( serv . status ))
+print (( " " * 8 ) + "process = {0} " . format ( repr ( serv . process )))
+print ( "" )
+
+print ( "Finding a service in a user process:" )
+serv = [ s for s in windows . system . services if s . process ][ 0 ]
+print ( " " + str ( serv ))
+print (( " " * 8 ) + "name = {0} " . format ( serv . name ))
+print (( " " * 8 ) + "description = {0} " . format ( serv . description ))
+print (( " " * 8 ) + "status = {0} " . format ( serv . status ))
+print (( " " * 8 ) + "process = {0} " . format ( repr ( serv . process )))
+print ( "" )
+
+print ( "Enumerating handles:" )
+handles = system . handles
+print ( " There are {0} handles:" . format ( len ( handles )))
+print ( " First handle is: " + str ( handles [ 0 ]))
+
+print ( " Enumerating handles of the current process:" )
+cp_handles = [ h for h in system . handles if h . dwProcessId == windows . current_process . pid ]
+print ( " There are {0} handles for this process" . format ( len ( cp_handles )))
+print ( " Looking for a File handle:" )
+file_h = [ h for h in cp_handles if h . type == "File" ][ 0 ]
+print ( " Handle is {0} " . format ( file_h ))
+print ( " Name is < {0} >" . format ( file_h . name ))
+
+
+
Output:
+
( cmd λ ) python system . py
+Basic system infos :
+ version = ( 6 , 3 )
+ bitness = 64
+ computer_name = HAKRIL - PC
+ product_type = VER_NT_WORKSTATION ( 0x1 L )
+ version_name = Windows 8.1
+
+There is 117 processes
+There is 1246 threads
+
+Dumping first logical drive :
+ < LogicalDrive "C: \" (DRIVE_FIXED)>
+ name = C : \
+ type = DRIVE_FIXED ( 0x3 L )
+ path = \Device \HarddiskVolume2
+
+Dumping first service :
+ < ServiceA "ACPI" >
+ name = ACPI
+ description = Microsoft ACPI Driver
+ status = ServiceStatus ( type = SERVICE_KERNEL_DRIVER ( 0x1 L ), state = SERVICE_RUNNING ( 0x4 L ), control_accepted = 1 L , flags = 0 L )
+ process = None
+
+Finding a service in a user process :
+ < ServiceA "Appinfo" >
+ name = Appinfo
+ description = Application Information
+ status = ServiceStatus ( type = SERVICE_WIN32_SHARE_PROCESS ( 0x20 L ), state = SERVICE_RUNNING ( 0x4 L ), control_accepted = 129 L , flags = 0 L )
+ process = < WinProcess "svchost.exe" pid 988 at 0x2e64750 >
+
+Enumerating handles :
+ There are 40664 handles :
+ First handle is : < Handle value =< 0x4 > in process pid = 4 >
+ Enumerating handles of the current process :
+ There are 255 handles for this process
+ Looking for a File handle :
+ Handle is < Handle value =< 0x4 > in process pid = 14340 >
+ Name is < \Device \ConDrv >
+
+
+
+
+
12.5. IAT hooking
+
import sys
+import os.path
+sys . path . append ( os . path . abspath ( __file__ + "\..\.." ))
+
+import _winreg
+import windows
+
+# Here is a demo of IAT hooking in python
+# We will hook the 'RegOpenKeyExA' entry of Python27.dll because it is easy to trigger !
+
+# First: let's create our hook
+# windows.hooks.RegOpenKeyExACallback is generated based on windows.generated_def.winfuncs
+@windows . hooks . RegOpenKeyExACallback
+def open_reg_hook ( hKey , lpSubKey , ulOptions , samDesired , phkResult , real_function ):
+ print ( "<in hook> Hook called | hKey = {0} | lpSubKey = < {1} >" . format ( hex ( hKey ), lpSubKey . value ))
+ # Our hook can choose to call the real_function or not
+ if "SECRET" in lpSubKey . value :
+ print ( "<in hook> Secret key asked, returning magic handle 0x12345678" )
+ # We must respect the hooked method return-value interface
+ phkResult [ 0 ] = 0x12345678
+ return 0
+ if "FAIL" in lpSubKey . value :
+ print ( "<in hook> Asked for a failing key: returning 0x2a" )
+ return 42
+ print ( "<in hook> Non-secret key : calling normal function" )
+ return real_function ()
+
+
+# Get the peb of our process
+peb = windows . current_process . peb
+
+# Get the pythonxx.dll module
+pythondll_module = [ m for m in peb . modules if m . name . startswith ( "python" ) and m . name . endswith ( ".dll" )][ 0 ]
+
+# Get the iat entries for DLL advapi32.dll
+adv_imports = pythondll_module . pe . imports [ 'advapi32.dll' ]
+
+# Get RegOpenKeyExA iat entry
+RegOpenKeyExA_iat = [ n for n in adv_imports if n . name == "RegOpenKeyExA" ][ 0 ]
+
+# Setup our hook
+RegOpenKeyExA_iat . set_hook ( open_reg_hook )
+
+# Use python native module _winreg that call 'RegOpenKeyExA'
+print ( "Asking for <MY_SECRET_KEY>" )
+v = _winreg . OpenKey ( 1234567 , "MY_SECRET_KEY" )
+print ( "Result = " + hex ( v . handle ))
+
+print ( "" )
+print ( "Asking for <MY_FAIL_KEY>" )
+try :
+ v = _winreg . OpenKey ( 1234567 , "MY_FAIL_KEY" )
+ print ( "Result = " + hex ( v . handle ))
+except WindowsError as e :
+ print ( repr ( e ))
+
+print ( "" )
+print ( "Asking for <HKEY_CURRENT_USER/Software>" )
+try :
+ v = _winreg . OpenKey ( _winreg . HKEY_CURRENT_USER , "Software" )
+ print ( "Result = " + hex ( v . handle ))
+except WindowsError as e :
+ print ( repr ( e ))
+
+
+
Output:
+
( cmd λ ) python iat_hook . py
+Asking for < MY_SECRET_KEY >
+< in hook > Hook called | hKey = 0x12d687 | lpSubKey = < MY_SECRET_KEY >
+< in hook > Secret key asked , returning magic handle 0x12345678
+Result = 0x12345678
+
+Asking for < MY_FAIL_KEY >
+< in hook > Hook called | hKey = 0x12d687 | lpSubKey = < MY_FAIL_KEY >
+< in hook > Asked for a failing key : returning 0x2a
+WindowsError ( 42 , 'Windows Error 0x2A' )
+
+Asking for < HKEY_CURRENT_USER / Software >
+< in hook > Hook called | hKey = 0x80000001 L | lpSubKey = < Software >
+< in hook > Non - secret key : calling normal function
+Result = 0x108
+
+
+
+
+
12.6. Network - socket exploration
+
import sys
+import os.path
+import socket
+sys . path . append ( os . path . abspath ( __file__ + "\..\.." ))
+
+import windows
+
+if not windows . utils . check_is_elevated ():
+ print ( "!!! Demo will fail because closing a connection require elevated process !!!" )
+
+print ( "Working on ipv4" )
+conns = windows . system . network . ipv4
+
+print ( "== Listening ==" )
+print ( "Some listening connections: {0} " . format ([ c for c in conns if not c . established ][: 3 ]))
+print ( "Listening ports are : {0} " . format ([ c . local_port for c in conns if not c . established ]))
+
+print ( "== Established ==" )
+print ( "Some established connections: {0} " . format ([ c for c in conns if c . established ][: 3 ]))
+
+TARGET_HOST = "localhost"
+TARGET_PORT = 80
+print ( "== connection to {0} : {1} ==" . format ( TARGET_HOST , TARGET_PORT ))
+s = socket . create_connection (( TARGET_HOST , TARGET_PORT ))
+
+our_connection = [ c for c in windows . system . network . ipv4 if c . established and c . remote_port == TARGET_PORT and c . remote_addr == s . getpeername ()[ 0 ]]
+
+print ( "Our connection is {0} " . format ( our_connection ))
+print ( "Sending YOP" )
+s . send ( "YOP" )
+print ( "Closing socket" )
+our_connection [ 0 ] . close ()
+print ( "Sending LAIT" )
+s . send ( "LAIT" )
+
+
+
Output:
+
( cmd λ ) python . exe network . py
+Working on ipv4
+== Listening ==
+Some listening connections : [ < TCP IPV4 Listening socket on 0.0 . 0.0 : 80 > , < TCP IPV4 Listening socket on 0.0 . 0.0 : 135 > , < TCP IPV4 Listening socket on 0.0 . 0.0 : 443 > ]
+Listening ports are : [ 80 , 135 , 443 , 445 , 902 , 912 , 5357 , 49152 , 49153 , 49154 , 49155 , 49157 , 49159 , 8307 , 25340 , 139 , 139 ]
+== Established ==
+Some established connections : [ < TCP IPV4 Connection 127.0 . 0.1 : 25340 -> 127.0 . 0.1 : 49472 > , < TCP IPV4 Connection 127.0 . 0.1 : 49173 -> 127.0 . 0.1 : 49174 > , < TCP IPV4 Connection 127.0 . 0.1 : 49174 -> 127.0 . 0.1 : 49173 > ]
+== connection to localhost : 80 ==
+Our connection is [ < TCP IPV4 Connection 127.0 . 0.1 : 49616 -> 127.0 . 0.1 : 80 > ]
+Sending YOP
+Closing socket
+Sending LAIT
+Traceback ( most recent call last ):
+File ". \n etwork.py" , line 45 , in < module >
+ s . send ( "LAIT" )
+socket . error : [ Errno 10054 ] An existing connection was forcibly closed by the remote host
+
+
+
+
+
12.7. Registry
+
import sys
+import os.path
+import pprint
+sys . path . append ( os . path . abspath ( __file__ + "\..\.." ))
+
+import windows
+
+registry = windows . system . registry
+print ( "Registry is < {0} >" . format ( registry ))
+
+current_user = registry ( "HKEY_CURRENT_USER" )
+print ( "HKEY_CURRENT_USER is < {0} >" . format ( current_user ))
+subkeys_name = [ s . name for s in current_user . subkeys ]
+print ( "HKEY_CURRENT_USER subkeys names are:" )
+pprint . pprint ( subkeys_name )
+
+print ( "Opening 'Software' in HKEY_CURRENT_USER: {0} " . format ( current_user ( "Software" )))
+print ( "We can also open it in one access: {0} " . format ( registry ( r"HKEY_CURRENT_USER\Sofware" )))
+print ( "Looking at CurrentVersion" )
+
+windows_info = registry ( "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion" )
+print ( "Key is {0} " . format ( windows_info ))
+
+print ( "values are:" )
+pprint . pprint ( windows_info . values )
+
+registered_owner = windows_info [ "RegisteredOwner" ]
+print ( "registered owner = < {0} >" . format ( registered_owner ))
+
+
+
Output:
+
( cmd λ ) python . exe registry . py
+Registry is << windows . registry . Registry object at 0x02941290 >>
+HKEY_CURRENT_USER is << PyHKey "HKEY_CURRENT_USER" >>
+HKEY_CURRENT_USER subkeys names are :
+[ 'AppEvents' ,
+'AppXBackupContentType' ,
+'Console' ,
+'Control Panel' ,
+'Environment' ,
+'EUDC' ,
+'Identities' ,
+'Keyboard Layout' ,
+'Network' ,
+'Printers' ,
+'Software' ,
+'System' ,
+'Volatile Environment' ]
+Opening 'Software' in HKEY_CURRENT_USER : < PyHKey "HKEY_CURRENT_USER\Software" >
+We can also open it in one access : < PyHKey "HKEY_CURRENT_USER\Sofware" >
+Looking at CurrentVersion
+Key is < PyHKey "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion" >
+values are :
+[ KeyValue ( name = 'SoftwareType' , value = u'System' , type = 1 ),
+KeyValue ( name = 'RegisteredOwner' , value = u'hakril' , type = 1 ),
+KeyValue ( name = 'InstallDate' , value = 0 , type = 4 ),
+...
+KeyValue ( name = 'PathName' , value = u'C: \\ Windows' , type = 1 )]
+registered owner = < KeyValue ( name = 'RegisteredOwner' , value = u'hakril' , type = 1 ) >
+
+
+
+
+
12.8. windows.wintrust
+
import sys
+import os.path
+sys . path . append ( os . path . abspath ( __file__ + "\..\.." ))
+
+import windows.wintrust
+
+TARGET_FILE = r"C:\windows\system32\ntdll.dll"
+print ( "Checking signature of < {0} >" . format ( TARGET_FILE ))
+print ( " is_signed: < {0} >" . format ( windows . wintrust . is_signed ( TARGET_FILE )))
+print ( " check_signature: < {0} >" . format ( windows . wintrust . check_signature ( TARGET_FILE )))
+
+sign_info = windows . wintrust . full_signature_information ( TARGET_FILE )
+print ( " full_signature_information:" )
+print ( " * signed < {0} >" . format ( sign_info . signed ))
+print ( " * catalog < {0} >" . format ( sign_info . catalog ))
+print ( " * catalogsigned < {0} >" . format ( sign_info . catalogsigned ))
+print ( " * additionalinfo < {0} >" . format ( sign_info . additionalinfo ))
+
+print ( "Checking signature of some loaded DLL" )
+for module in windows . current_process . peb . modules [: 5 ]:
+ path = module . fullname
+ is_signed = windows . wintrust . is_signed ( path )
+ if is_signed :
+ print ( "< {0} > : {1} " . format ( path , is_signed ))
+ else :
+ sign_info = windows . wintrust . full_signature_information ( path )
+ print ( "< {0} > : {1} ( {2} )" . format ( path , is_signed , sign_info [ 3 ]))
+
+
+
+
+
Output:
+
( cmd λ ) python . \wintrust . py
+Checking signature of < C : \windows \system32 \ntdll . dll >
+is_signed : < True >
+check_signature : < 0 >
+full_signature_information :
+ * signed < True >
+ * catalog < C : \Windows \system32 \CatRoot \{ F750E6C3 - 38 EE - 11 D1 - 85 E5 - 00 C04FC295EE } \Package_35_for_KB3128650 ~ 31 bf3856ad364e35 ~ amd64 ~~ 6.3 . 1.2 . cat >
+ * catalogsigned < True >
+ * additionalinfo < 0 >
+Checking signature of some loaded DLL
+< c : \python27 \python . exe > : False ( TRUST_E_NOSIGNATURE ( 0x800b0100 L ))
+< c : \windows \system32 \ntdll . dll > : True
+< c : \windows \system32 \kernel32 . dll > : True
+< c : \windows \system32 \kernelbase . dll > : True
+< c : \windows \system32 \python27 . dll > : False ( TRUST_E_NOSIGNATURE ( 0x800b0100 L ))
+
+
+
+
+
12.9. VectoredException()
+
+
12.9.1. In local process
+
import sys
+import os.path
+import pprint
+sys . path . append ( os . path . abspath ( __file__ + "\..\.." ))
+
+import ctypes
+import windows
+from windows.winobject.exception import VectoredException
+import windows.generated_def.windef as windef
+from windows.generated_def.winstructs import *
+
+
+@VectoredException
+def handler ( exc ):
+ print ( "==Entry of VEH handler==" )
+ if exc [ 0 ] . ExceptionRecord [ 0 ] . ExceptionCode == EXCEPTION_ACCESS_VIOLATION :
+ target_addr = ctypes . cast ( exc [ 0 ] . ExceptionRecord [ 0 ] . ExceptionInformation [ 1 ], ctypes . c_void_p ) . value
+ print ( "Instr at {0} accessed to addr {1} " . format ( hex ( exc [ 0 ] . ExceptionRecord [ 0 ] . ExceptionAddress ), hex ( target_addr )))
+ print ( "Resetting page protection to <PAGE_READWRITE>" )
+ windows . winproxy . VirtualProtect ( target_page , 0x1000 , windef . PAGE_READWRITE )
+ exc [ 0 ] . ContextRecord [ 0 ] . EEFlags . TF = 1
+ return windef . EXCEPTION_CONTINUE_EXECUTION
+ else :
+ print ( "Exception of type {0} " . format ( exc [ 0 ] . ExceptionRecord [ 0 ] . ExceptionCode ))
+ print ( "Resetting page protection to <PAGE_NOACCESS>" )
+ windows . winproxy . VirtualProtect ( target_page , 0x1000 , windef . PAGE_NOACCESS )
+ return windef . EXCEPTION_CONTINUE_EXECUTION
+
+
+windows . winproxy . AddVectoredExceptionHandler ( 0 , handler )
+
+target_page = windows . current_process . virtual_alloc ( 0x1000 )
+print ( "Protected page is at < {0} >" . format ( hex ( target_page )))
+print ( "Setting page protection to <PAGE_NOACCESS>" )
+windows . winproxy . VirtualProtect ( target_page , 0x1000 , windef . PAGE_NOACCESS )
+
+print ( "" )
+v = ctypes . c_uint . from_address ( target_page ) . value
+print ( "Value 1 read" )
+
+print ( "" )
+v = ctypes . c_uint . from_address ( target_page + 0x10 ) . value
+print ( "Value 2 read" )
+
+
+
Output:
+
( cmd λ ) python . exe veh_segv . py
+Protected page is at < 0x1db0000 >
+Setting page protection to < PAGE_NOACCESS >
+
+== Entry of VEH handler ==
+Instr at 0x1d1ab574 accessed to addr 0x1db0000
+Resetting page protection to < PAGE_READWRITE >
+== Entry of VEH handler ==
+Exception of type EXCEPTION_SINGLE_STEP ( 0x80000004 L )
+Resetting page protection to < PAGE_NOACCESS >
+Value 1 read
+
+== Entry of VEH handler ==
+Instr at 0x1d1ab574 accessed to addr 0x1db0010
+Resetting page protection to < PAGE_READWRITE >
+== Entry of VEH handler ==
+Exception of type EXCEPTION_SINGLE_STEP ( 0x80000004 L )
+Resetting page protection to < PAGE_NOACCESS >
+Value 2 read
+
+
+
+
+
12.9.2. In remote process
+
import sys
+import os.path
+import pprint
+sys . path . append ( os . path . abspath ( __file__ + "\..\.." ))
+
+import windows
+import windows.test
+
+from windows.generated_def.winstructs import *
+
+python_code = """
+import windows
+import ctypes
+import windows
+from windows.winobject.exception import VectoredException
+import windows.generated_def.windef as windef
+from windows.generated_def.winstructs import *
+
+windows.utils.create_console()
+
+module_to_trace = "gdi32.dll"
+nb_repeat = [5]
+
+@VectoredException
+def handler(exc):
+ if exc[0].ExceptionRecord[0].ExceptionCode == EXCEPTION_ACCESS_VIOLATION:
+ print("")
+ target_addr = ctypes.cast(exc[0].ExceptionRecord[0].ExceptionInformation[1], ctypes.c_void_p).value
+ print("Instr at {0} accessed to addr {1} ( {2} )".format(hex(exc[0].ExceptionRecord[0].ExceptionAddress), hex(target_addr), module_to_trace))
+ windows.winproxy.VirtualProtect(target_page, code_size, windef.PAGE_EXECUTE_READWRITE)
+ nb_repeat[0] -= 1
+ if nb_repeat[0]:
+ exc[0].ContextRecord[0].EEFlags.TF = 1
+ else:
+ print("No more tracing !")
+ return windef.EXCEPTION_CONTINUE_EXECUTION
+ else:
+ print("Exception of type {0} ".format(exc[0].ExceptionRecord[0].ExceptionCode))
+ print("Resetting page protection to <PAGE_READWRITE>")
+ windows.winproxy.VirtualProtect(target_page, code_size, windef.PAGE_READWRITE)
+ return windef.EXCEPTION_CONTINUE_EXECUTION
+
+
+windows.winproxy.AddVectoredExceptionHandler(0, handler)
+
+print("Tracing execution in module: < {0} >".format(module_to_trace))
+
+module = [x for x in windows.current_process.peb.modules if x.name == module_to_trace][0]
+target_page = module.baseaddr
+code_size = module.pe.get_OptionalHeader().SizeOfCode
+
+print("Protected page is at {0} ".format(hex(target_page)))
+windows.winproxy.VirtualProtect(target_page, code_size, windef.PAGE_READWRITE)
+"""
+
+c = windows . test . pop_calc_64 ( dwCreationFlags = CREATE_SUSPENDED )
+x = c . execute_python ( python_code )
+
+c . threads [ 0 ] . resume ()
+
+import time
+time . sleep ( 0.1 )
+
+for t in c . threads :
+ t . suspend ()
+
+time . sleep ( 1 )
+c . exit ()
+
+
+
+
Output:
+
(cmd λ) python .exe.\samples\remote_veh_segv.py
+(In another console)
+
+Tracing execution in module: <gdi32.dll>
+Protected page is at 0x7ffa3c700000L
+
+Instr at 0x7ffa3c70f0f0L accessed to addr 0x7ffa3c70f0f0L (gdi32.dll)
+Exception of type EXCEPTION_SINGLE_STEP(0x80000004L)
+Resetting page protection to <PAGE_READWRITE>
+
+Instr at 0x7ffa3c70f0f5L accessed to addr 0x7ffa3c70f0f5L (gdi32.dll)
+Exception of type EXCEPTION_SINGLE_STEP(0x80000004L)
+Resetting page protection to <PAGE_READWRITE>
+
+Instr at 0x7ffa3c70f0faL accessed to addr 0x7ffa3c70f0faL (gdi32.dll)
+Exception of type EXCEPTION_SINGLE_STEP(0x80000004L)
+Resetting page protection to <PAGE_READWRITE>
+
+Instr at 0x7ffa3c70f0ffL accessed to addr 0x7ffa3c70f0ffL (gdi32.dll)
+Exception of type EXCEPTION_SINGLE_STEP(0x80000004L)
+Resetting page protection to <PAGE_READWRITE>
+
+Instr at 0x7ffa3c70f100L accessed to addr 0x7ffa3c70f100L (gdi32.dll)
+No more tracing !
+
+
+
+
+
+
12.10. Debugging
+
+
12.10.1. Debugger
+
import sys
+import os.path
+import pprint
+sys . path . append ( os . path . abspath ( __file__ + "\..\.." ))
+
+import windows
+import windows.test
+import windows.debug
+
+from windows.generated_def.winstructs import *
+
+
+
+class MyDebugger ( windows . debug . Debugger ):
+ def on_exception ( self , exception ):
+ code = exception . ExceptionRecord . ExceptionCode
+ addr = exception . ExceptionRecord . ExceptionAddress
+ print ( "Got exception {0} at 0x {1:x} " . format ( code , addr ))
+
+
+class PrintUnicodeString ( windows . debug . Breakpoint ):
+ def __init__ ( self , addr , argument_position ):
+ super ( PrintUnicodeString , self ) . __init__ ( addr )
+ self . arg_pos = argument_position
+
+
+ def trigger ( self , dbg , exc ):
+ p = dbg . current_process
+ t = dbg . current_thread
+ esp = t . context . Esp
+
+ unicode_string_addr = p . read_ptr ( esp + ( self . arg_pos + 1 ) * 4 )
+ wstring_addr = p . read_ptr ( unicode_string_addr + 4 )
+ dll_loaded = p . read_wstring ( wstring_addr )
+ print ( "Loading < {0} >" . format ( dll_loaded ))
+
+ if dll_loaded . endswith ( "ole32.dll" ):
+ print ( "Ask to load <ole32.dll>: exiting process" )
+ dbg . current_process . exit ()
+
+
+calc = windows . test . pop_calc_32 ( dwCreationFlags = DEBUG_PROCESS )
+d = MyDebugger ( calc )
+d . add_bp ( PrintUnicodeString ( "ntdll!LdrLoadDll" , argument_position = 2 ))
+d . loop ()
+
+
+
+
Ouput:
+
( cmd λ ) python . exe . \samples \debugger_print_LdrLoaddll . py
+Loading < KERNEL32 . DLL >
+Got exception EXCEPTION_BREAKPOINT ( 0x80000003 L ) at 0x77a73bad
+Loading < C : \Windows \system32 \IMM32 . DLL >
+Loading < C : \Windows \system32 \uxtheme . dll >
+Loading < C : \Windows \system32 \uxtheme . dll >
+Loading < C : \Windows \system32 \uxtheme . dll >
+Loading < C : \Windows \system32 \uxtheme . dll >
+Loading < kernel32 . dll >
+Loading < C : \Windows \WinSxS \x86_microsoft . windows . gdiplus_6595b64144ccf1df_1 . 1.9600 . 17415 _none_dad8722c5bcc2d8f \gdiplus . dll >
+Loading < comctl32 . dll >
+Loading < comctl32 . dll >
+Loading < comctl32 . dll >
+Loading < C : \Windows \system32 \shell32 . dll >
+Loading < C : \Windows \SYSTEM32 \WINMM . dll >
+Loading < C : \Windows \system32 \ole32 . dll >
+Ask to load < ole32 . dll > : exiting process
+
+
+
+
12.10.1.1. Single stepping
+
import sys
+import os.path
+import pprint
+sys . path . append ( os . path . abspath ( __file__ + "\..\.." ))
+
+import windows
+import windows.test
+import windows.debug
+
+import windows.native_exec.simple_x86 as x86
+from windows.generated_def.winstructs import *
+
+
+class MyDebugger ( windows . debug . Debugger ):
+ def __init__ ( self , * args , ** kwargs ):
+ super ( MyDebugger , self ) . __init__ ( * args , ** kwargs )
+ self . single_step_counter = 0
+
+ def on_exception ( self , exception ):
+ code = exception . ExceptionRecord . ExceptionCode
+ addr = exception . ExceptionRecord . ExceptionAddress
+ print ( "Got exception {0} at 0x {1:x} " . format ( code , addr ))
+
+ def on_single_step ( self , exception ):
+ code = exception . ExceptionRecord . ExceptionCode
+ addr = exception . ExceptionRecord . ExceptionAddress
+ print ( "Got single_step {0} at 0x {1:x} " . format ( code , addr ))
+ self . single_step_counter -= 1
+ if self . single_step_counter > 0 :
+ return self . single_step ()
+ else :
+ print ( "No more single step: exiting" )
+ self . current_process . exit ()
+
+
+class SingleStepOnWrite ( windows . debug . MemoryBreakpoint ):
+ """Check that BP/dbg can trigger single step and that instruction follows"""
+ def trigger ( self , dbg , exc ):
+ fault_addr = exc . ExceptionRecord . ExceptionInformation [ 1 ]
+ import pdb ; pdb . set_trace ()
+ eip = dbg . current_thread . context . pc
+ print ( "Instruction at < {0:#x} > wrote at < {1:#x} >" . format ( eip , fault_addr ))
+ dbg . single_step_counter = 4
+ return dbg . single_step ()
+
+
+calc = windows . test . pop_calc_32 ( dwCreationFlags = DEBUG_PROCESS )
+d = MyDebugger ( calc )
+
+code = calc . virtual_alloc ( 0x1000 )
+data = calc . virtual_alloc ( 0x1000 )
+
+injected = x86 . MultipleInstr ()
+injected += x86 . Mov ( "EAX" , 0 )
+injected += x86 . Mov ( x86 . deref ( data ), "EAX" )
+injected += x86 . Add ( "EAX" , 4 )
+injected += x86 . Mov ( x86 . deref ( data + 4 ), "EAX" )
+injected += x86 . Add ( "EAX" , 8 )
+injected += x86 . Mov ( x86 . deref ( data + 8 ), "EAX" )
+injected += x86 . Nop ()
+injected += x86 . Nop ()
+injected += x86 . Ret ()
+
+calc . write_memory ( code , injected . get_code ())
+d . add_bp ( SingleStepOnWrite ( data , size = 8 , events = "W" ))
+calc . create_thread ( code , 0 )
+d . loop ()
+
+
+
+
Ouput:
+
( cmd λ ) python . exe . \samples \debugger_membp_singlestep . py
+Got exception EXCEPTION_BREAKPOINT ( 0x80000003 L ) at 0x77ae3c7d
+Instruction at < 0x8d0006 > wrote at < 0x8e0000 >
+Got single_step EXCEPTION_SINGLE_STEP ( 0x80000004 L ) at 0x8d000c
+Got single_step EXCEPTION_SINGLE_STEP ( 0x80000004 L ) at 0x8d0011
+Instruction at < 0x8d0011 > wrote at < 0x8e0004 >
+Got single_step EXCEPTION_SINGLE_STEP ( 0x80000004 L ) at 0x8d0017
+Got single_step EXCEPTION_SINGLE_STEP ( 0x80000004 L ) at 0x8d001c
+Got single_step EXCEPTION_SINGLE_STEP ( 0x80000004 L ) at 0x8d0022
+Got single_step EXCEPTION_SINGLE_STEP ( 0x80000004 L ) at 0x8d0023
+No more single step : exiting
+
+
+
+
+
+
import sys
+import os.path
+import pprint
+sys . path . append ( os . path . abspath ( __file__ + "\..\.." ))
+
+import windows
+import windows.test
+import windows.debug
+
+from windows.generated_def.winstructs import *
+
+class MyFunctionBP ( windows . debug . FunctionBP ):
+ def __init__ ( self , target , addr = None ):
+ super ( MyFunctionBP , self ) . __init__ ( target , addr )
+ self . target_name = target . target_func
+ self . counter = 3
+
+ def trigger ( self , dbg , exc ):
+ if not self . counter :
+ print ( "Exiting process" )
+ dbg . current_process . exit ()
+ return
+ params = self . extract_arguments ( dbg . current_process , dbg . current_thread )
+ filename = params [ "ObjectAttributes" ] . contents . ObjectName . contents . Buffer
+ handle_addr = params [ "FileHandle" ] . value
+ self . data = ( filename , handle_addr )
+ self . break_on_ret ( dbg , exc )
+
+ def ret_trigger ( self , dbg , exc ):
+ filename , handle_addr = self . data
+ ret_value = dbg . current_thread . context . func_result # EAX / RAX depending of bitness
+ handle_value = dbg . current_process . read_ptr ( handle_addr )
+ if ret_value :
+ print ( "NtCreateFile of < {0} > FAILED (result= {1:#x} )" . format ( filename , ret_value ))
+ return
+ print ( "NtCreateFile of < {0} >: handle = {1:#x} " . format ( filename , handle_value ))
+ # Manual verification
+ fhandle = [ h for h in windows . system . handles if h . dwProcessId == dbg . current_process . pid and h . wValue == handle_value ]
+ if not fhandle :
+ raise ValueError ( "handle not found!" )
+ fhandle = fhandle [ 0 ]
+ print ( "Handle manually found! typename=< {0} >, name=< {1} >" . format ( fhandle . type , fhandle . name ))
+ print ( "" )
+ self . counter -= 1
+
+calc = windows . test . pop_calc_32 ( dwCreationFlags = DEBUG_PROCESS )
+d = windows . debug . Debugger ( calc )
+d . add_bp ( MyFunctionBP ( windows . winproxy . NtCreateFile ))
+d . loop ()
+
+
+
Ouput:
+
NtCreateFile of <\??\C:\Windows\syswow64\en-US\calc.exe.mui>: handle = 0xac
+Handle manually found! typename=<File>, name=<\Device\HarddiskVolume2\Windows\SysWOW64\en-US\calc.exe.mui>
+
+NtCreateFile of <\Device\DeviceApi\CMApi>: handle = 0x108
+Handle manually found! typename=<File>, name=<\Device\DeviceApi>
+
+NtCreateFile of <\??\C:\Windows\Fonts\staticcache.dat>: handle = 0x154
+Handle manually found! typename=<File>, name=<\Device\HarddiskVolume2\Windows\Fonts\StaticCache.dat>
+
+Exiting process
+
+
+
+
+
+
12.10.2. LocalDebugger
+
import sys
+import os.path
+import pprint
+sys . path . append ( os . path . abspath ( __file__ + "\..\.." ))
+
+import windows
+from windows.generated_def.winstructs import *
+import windows.native_exec.simple_x86 as x86
+
+class SingleSteppingDebugger ( windows . debug . LocalDebugger ):
+ SINGLE_STEP_COUNT = 4
+ def on_exception ( self , exc ):
+ code = self . get_exception_code ()
+ context = self . get_exception_context ()
+ print ( "EXCEPTION !!!! Got a {0} at 0x {1:x} " . format ( code , context . pc ))
+ self . SINGLE_STEP_COUNT -= 1
+ if self . SINGLE_STEP_COUNT :
+ return self . single_step ()
+ return EXCEPTION_CONTINUE_EXECUTION
+
+class RewriteBreakpoint ( windows . debug . HXBreakpoint ):
+ def trigger ( self , dbg , exc ):
+ context = dbg . get_exception_context ()
+ print ( "GOT AN HXBP at 0x {0:x} " . format ( context . pc ))
+ # Rewrite the infinite loop with 2 nop
+ windows . current_process . write_memory ( self . addr , " \x90\x90 " )
+ # Ask for a single stepping
+ return dbg . single_step ()
+
+
+d = SingleSteppingDebugger ()
+# Infinite loop + nop + ret
+code = x86 . assemble ( "label :begin; jmp :begin; nop; ret" )
+func = windows . native_exec . create_function ( code , [ PVOID ])
+print ( "Code addr = 0x {0:x} " . format ( func . code_addr ))
+# Create a thread that will infinite loop
+t = windows . current_process . create_thread ( func . code_addr , 0 )
+# Add a breakpoint on the infitine loop
+d . add_bp ( RewriteBreakpoint ( func . code_addr ))
+t . wait ()
+print ( "Done!" )
+
+
+
+
+
Ouput:
+
(cmd λ) python.exe .\samples\local_debugger.py
+Code addr = 0xcf0002
+GOT AN HXBP at 0xcf0002
+EXCEPTION !!!! Got a EXCEPTION_SINGLE_STEP(0x80000004L) at 0xcf0003
+EXCEPTION !!!! Got a EXCEPTION_SINGLE_STEP(0x80000004L) at 0xcf0004
+EXCEPTION !!!! Got a EXCEPTION_SINGLE_STEP(0x80000004L) at 0xcf0005
+EXCEPTION !!!! Got a EXCEPTION_SINGLE_STEP(0x80000004L) at 0x770d7c04
+Done!
+
+
+
import sys
+import os.path
+import pprint
+sys . path . append ( os . path . abspath ( __file__ + "\..\.." ))
+
+import ctypes
+import windows
+import windows.test
+
+from windows.generated_def.winstructs import *
+
+remote_code = """
+import windows
+from windows.generated_def.winstructs import *
+
+windows.utils.create_console()
+
+class YOLOHXBP(windows.debug.HXBreakpoint):
+ def trigger(self, dbg, exc):
+ p = windows.current_process
+ arg_pos = 2
+ context = dbg.get_exception_context()
+ esp = context.Esp
+ unicode_string_addr = p.read_ptr(esp + (arg_pos + 1) * 4)
+ wstring_addr = p.read_ptr(unicode_string_addr + 4)
+ dll_loaded = p.read_wstring(wstring_addr)
+ print("I AM LOADING < {0} >".format(dll_loaded))
+
+d = windows.debug.LocalDebugger()
+
+exp = windows.current_process.peb.modules[1].pe.exports
+#windows.utils.FixedInteractiveConsole(locals()).interact()
+ldr = exp["LdrLoadDll"]
+d.add_bp(YOLOHXBP(ldr))
+
+"""
+
+c = windows . test . pop_calc_32 ( dwCreationFlags = CREATE_SUSPENDED )
+c . execute_python ( remote_code )
+c . threads [ 0 ] . resume ()
+
+import time
+time . sleep ( 2 )
+c . exit ()
+
+
+
Ouput:
+
( cmd λ ) python . exe . \samples \local_debugger_remote_process . py
+( In another console )
+I AM LOADING < C : \Windows \system32 \uxtheme . dll >
+I AM LOADING < C : \Windows \system32 \uxtheme . dll >
+I AM LOADING < C : \Windows \system32 \uxtheme . dll >
+I AM LOADING < C : \Windows \system32 \uxtheme . dll >
+I AM LOADING < kernel32 . dll >
+I AM LOADING < C : \Windows \WinSxS \x86_microsoft . windows . gdiplus_6595b64144ccf1df_1 . 1.9600 . 17415 _none_dad8722c5bcc2d8f \gdiplus . dll >
+I AM LOADING < comctl32 . dll >
+I AM LOADING < comctl32 . dll >
+I AM LOADING < comctl32 . dll >
+I AM LOADING < comctl32 . dll >
+I AM LOADING < comctl32 . dll >
+I AM LOADING < comctl32 >
+I AM LOADING < C : \Windows \SysWOW64 \oleacc . dll >
+I AM LOADING < OLEAUT32 . DLL >
+I AM LOADING < C : \Windows \system32 \ole32 . dll >
+I AM LOADING < C : \Windows \system32 \MSCTF . dll >
+I AM LOADING < C : \Windows \SysWOW64 \msxml6 . dll >
+I AM LOADING < C : \Windows \system32 \shell32 . dll >
+I AM LOADING < C : \Windows \SYSTEM32 \WINMM . dll >
+I AM LOADING < C : \Windows \system32 \ole32 . dll >
+
+
+
+
+
12.10.3. Make WMI requests
+
import sys
+import os.path
+import pprint
+sys . path . append ( os . path . abspath ( __file__ + "\..\.." ))
+
+import windows
+
+print ( "WMI requester is {0} " . format ( windows . system . wmi ))
+
+print ( "Selecting * from 'Win32_Process'" )
+result = windows . system . wmi . select ( "Win32_Process" )
+
+print ( "They are < {0} > processes" . format ( len ( result )))
+
+print ( "Looking for ourself via pid" )
+us = [ p for p in result if int ( p [ "ProcessId" ]) == windows . current_process . pid ][ 0 ]
+
+print ( "Some info about our process:" )
+print ( " * {0} -> {1} " . format ( "Name" , us [ "Name" ]))
+print ( " * {0} -> {1} " . format ( "ProcessId" , us [ "ProcessId" ]))
+print ( " * {0} -> {1} " . format ( "OSName" , us [ "OSName" ]))
+print ( " * {0} -> {1} " . format ( "UserModeTime" , us [ "UserModeTime" ]))
+print ( " * {0} -> {1} " . format ( "WindowsVersion" , us [ "WindowsVersion" ]))
+print ( " * {0} -> {1} " . format ( "CommandLine" , us [ "CommandLine" ]))
+
+print ( "<Select Caption,FileSystem,FreeSpace from Win32_LogicalDisk>:" )
+for vol in windows . system . wmi . select ( "Win32_LogicalDisk" , [ "Caption" , "FileSystem" , "FreeSpace" ]):
+ print ( " * " + str ( vol ))
+
+
+
+
+
+
Ouput:
+
( cmd λ ) python . \samples \wmi_request . py
+WMI requester is < windows . winobject . wmi . WmiRequester object at 0x02B37EF0 >
+Selecting * from 'Win32_Process'
+They are < 92 > processes
+Looking for ourself via pid
+Some info about our process :
+ * Name -> python . exe
+ * ProcessId -> 7968
+ * OSName -> Microsoft Windows 8.1 Pro | C : \Windows | \Device \Harddisk0 \Partition2
+ * UserModeTime -> 2812500
+ * WindowsVersion -> 6.3 . 9600
+ * CommandLine -> python . exe . \samples \wmi_request . py
+< Select Caption , FileSystem , FreeSpace from Win32_LogicalDisk > :
+ * { 'Caption' : u'C:' , 'FreeSpace' : u'43991547904' , 'FileSystem' : u'NTFS' }
+ * { 'Caption' : u'E:' , 'FreeSpace' : u'82776027136' , 'FileSystem' : u'NTFS' }
+ * { 'Caption' : u'F:' , 'FreeSpace' : u'5711265792' , 'FileSystem' : u'FAT32' }
+ * { 'Caption' : u'G:' , 'FreeSpace' : None , 'FileSystem' : None }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/search.html b/docs/build/html/search.html
new file mode 100644
index 0000000..e0eefef
--- /dev/null
+++ b/docs/build/html/search.html
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+ Search — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Search
+
+
+
+ Please activate JavaScript to enable the search
+ functionality.
+
+
+
+ From here you can search these documents. Enter your search
+ words into the box below and click "search". Note that the search
+ function will automatically search for all of the words. Pages
+ containing fewer words won't appear in the result list.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js
new file mode 100644
index 0000000..6d12cee
--- /dev/null
+++ b/docs/build/html/searchindex.js
@@ -0,0 +1 @@
+Search.setIndex({envversion:49,filenames:["debug","index"],objects:{"windows.debug":{Breakpoint:[0,1,1,""],Debugger:[0,1,1,""],FunctionBP:[0,1,1,""],HXBreakpoint:[0,1,1,""],LocalDebugger:[0,1,1,""],MemoryBreakpoint:[0,1,1,""]},"windows.debug.Breakpoint":{trigger:[0,2,1,""]},"windows.debug.Debugger":{DisabledMemoryBreakpoint:[0,2,1,""],__init__:[0,2,1,""],add_bp:[0,2,1,""],attach:[0,3,1,""],debug:[0,3,1,""],del_bp:[0,2,1,""],disable_all_memory_breakpoints:[0,2,1,""],get_exception_bitness:[0,2,1,""],get_memory_breakpoint_at:[0,2,1,""],loop:[0,2,1,""],on_create_process:[0,2,1,""],on_create_thread:[0,2,1,""],on_exception:[0,2,1,""],on_exit_process:[0,2,1,""],on_exit_thread:[0,2,1,""],on_load_dll:[0,2,1,""],on_output_debug_string:[0,2,1,""],on_rip:[0,2,1,""],on_single_step:[0,2,1,""],on_unload_dll:[0,2,1,""],restore_all_memory_breakpoints:[0,2,1,""],single_step:[0,2,1,""]},"windows.debug.FunctionBP":{break_on_ret:[0,2,1,""],extract_arguments:[0,2,1,""],ret_trigger:[0,2,1,""],trigger:[0,2,1,""]},"windows.debug.HXBreakpoint":{trigger:[0,2,1,""]},"windows.debug.LocalDebugger":{add_bp:[0,2,1,""],del_bp:[0,2,1,""],get_exception_code:[0,2,1,""],get_exception_context:[0,2,1,""],on_exception:[0,2,1,""],single_step:[0,2,1,""]},"windows.debug.MemoryBreakpoint":{__init__:[0,2,1,""],trigger:[0,2,1,""]},windows:{debug:[0,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","classmethod","Python class method"]},objtypes:{"0":"py:module","1":"py:class","2":"py:method","3":"py:classmethod"},terms:{"0x10":0,"32b":0,"64bit":0,"break":0,"class":0,"default":0,"function":[0,1],"int":0,"public":0,"return":0,__init__:0,abl:0,accept:0,access:0,add:0,add_bp:0,addr:0,address:0,addvectoredexceptionhandl:0,affect:0,after:0,all:0,ani:0,api:[0,1],apinam:0,arg:0,argument:0,around:0,aspx:0,assembler:1,attach:0,base:0,behaviour:0,bit:0,break_on_ret:0,call:0,callabl:0,callback:0,callind:0,can:0,caus:0,chang:0,check:1,classmethod:0,code:[0,1],com:[0,1],compon:1,content:1,context:[0,1],correspond:0,cproc:0,cpuid:1,creat:0,create_process:0,create_thread:0,cross:1,cthread:0,current:0,current_process:[0,1],current_thread:0,data:0,dbg:0,dbg_continue:0,dbg_exception_not_handled:0,dead:0,debug_exeception_event:0,debug_str:0,debugingg:0,del_bp:0,delet:0,desktop:0,disabl:0,disable_all_memory_breakpoint:0,disabledmemorybreakpoint:0,disassembl:0,dispatch:0,dll:0,document:0,don:0,drive:1,drx:0,dwcreationflag:0,earli:1,eexception_debug_info32:0,eexception_debug_info64:0,els:0,embed:0,event:0,exampl:1,exc:0,except:0,exception:1,exceptioncod:0,exec:0,execut:[0,1],exit:0,exit_process:0,exit_thread:0,expect:0,explor:1,explorat:1,extract:0,extract_argu:0,fals:0,fault:0,follow:0,form:0,from:0,functionbp:0,gate:1,get:0,get_exception_bit:0,get_exception_cod:0,get_exception_context:0,get_memory_breakpoint_at:0,given:0,handl:[0,1],hardwar:0,hardware_exec_bp:0,have:0,heaven:1,helper:1,hit:0,hook:1,http:0,hxbreakpoint:0,iat:1,implement:[0,1],index:1,int3:0,interest:0,interfac:[0,1],internal:1,know:0,known:0,kwd:0,librari:0,load:[0,1],load_dll:0,logic:1,loop:0,make:[0,1],manag:[0,1],map:0,mean:0,membp:0,memori:0,memory_breakpoint:0,memorybreakpoint:0,method:0,microsoft:0,might:0,model:1,modul:1,ms679286:0,ms679287:0,ms679334:0,ms679335:0,ms680351:0,ms680545:0,ms680587:0,ms681403:0,msdn:0,much:0,must:0,nativ:1,native_exec:1,nativeutil:1,network:1,non:0,none:0,now:0,object:1,occur:0,offset:0,on_create_process:0,on_create_thread:0,on_except:0,on_exit_process:0,on_exit_thread:0,on_load_dl:0,on_output_debug_str:0,on_rip:0,on_single_step:0,on_unload_dl:0,onli:0,ordereddict:0,origin:0,other:0,page:[0,1],param:0,paramet:0,pars:1,pass:0,path:0,peb:1,pefile:1,perform:0,process:[0,1],progress:1,protocol:1,put:[0,1],read:0,real:0,registri:1,relat:1,remot:[0,1],remotectyp:1,repres:0,request:[0,1],restor:0,restore_all_memory_breakpoint:0,result:0,ret_trigg:0,right:0,rip_info:0,rwx:0,sad:0,sampl:[0,1],search:1,see:0,servic:1,setup:0,should:0,show_window:0,signatur:1,simple_x64:1,simple_x86:1,singl:0,single_step:0,size:0,socket:1,some:0,soon:0,sourc:0,standard:0,standard_bp:0,step:0,str:0,string:0,structur:[0,1],subclass:0,system:1,syswow64:1,target:0,tested:0,them:0,thi:0,those:0,thread:[0,1],trigger:0,type:0,unload_dl:0,useful:0,using:1,util:1,utiliti:1,valu:0,vectoredexcept:[0,1],virtual_protect:0,virtualalloc:1,volum:1,wai:0,when:0,where:0,which:0,win32:0,winobject:0,winprocess:[0,1],winproxi:[0,1],wintrust:1,without:0,wmi:1,won:0,work:1,write:0,x64:1,x86:1,you:0},titles:["7. windows.debug – Debugging","Welcome to PythonForWindows’s documentation!"],titleterms:{breakpoint:0,debug:0,debugg:0,document:1,indice:1,localdebugg:0,pythonforwindow:1,tabl:1,welcom:1,window:0}})
\ No newline at end of file
diff --git a/docs/build/html/service.html b/docs/build/html/service.html
new file mode 100644
index 0000000..1d7237d
--- /dev/null
+++ b/docs/build/html/service.html
@@ -0,0 +1,243 @@
+
+
+
+
+
+
+
+ 2.7. Service — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2.7. Service
+
+
+
+class windows.winobject.service.ServiceStatus( type , state , control_accepted , flags )
+type might be one of:
+
+
+SERVICE_KERNEL_DRIVER(0x1L)
+SERVICE_FILE_SYSTEM_DRIVER(0x2L)
+SERVICE_WIN32_OWN_PROCESS(0x10L)
+SERVICE_WIN32_SHARE_PROCESS(0x20L)
+SERVICE_INTERACTIVE_PROCESS(0x100L)
+
+
+state might be one of:
+
+
+SERVICE_STOPPED(0x1L)
+SERVICE_START_PENDING(0x2L)
+SERVICE_STOP_PENDING(0x3L)
+SERVICE_RUNNING(0x4L)
+SERVICE_CONTINUE_PENDING(0x5L)
+SERVICE_PAUSE_PENDING(0x6L)
+SERVICE_PAUSED(0x7L)
+
+
+flags might be one of:
+
+
+0
+SERVICE_RUNS_IN_SYSTEM_PROCESS(0x1L)
+
+
+
+
+control_accepted
+Alias for field number 2
+
+
+
+
+flags
+Alias for field number 3
+
+
+
+
+state
+Alias for field number 1
+
+
+
+
+type
+Alias for field number 0
+
+
+
+
+
+
+class windows.winobject.service.ServiceA[source]
+Bases: windows.winobject.service.Service , windows.generated_def.winstructs._ENUM_SERVICE_STATUS_PROCESSA
+A Service object with ascii data
+
+
+description
+The description of the service
+
+
+
+
+
+name
+The name of the service
+
+
+
+
+
+process
+The process running the service (if any)
+
+
+
+
+
+status
+The status of the service
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/utils.html b/docs/build/html/utils.html
new file mode 100644
index 0000000..e4bc134
--- /dev/null
+++ b/docs/build/html/utils.html
@@ -0,0 +1,217 @@
+
+
+
+
+
+
+
+ 5. windows.utils – Windows Utilities — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
5. windows.utils – Windows Utilities
+
+
5.1. Context Managers
+
windows.utils provides some context managers wrapping standard contextual operations
+like VirtualProtect or SysWow Redirection
+
+
5.1.1. VirtualProtected
+
+
+class windows.utils.VirtualProtected( addr , size , new_protect ) [source]
+A context manager usable like VirtualProtect that will restore the old protection at exit
+with utils . VirtualProtected ( IATentry . addr , ctypes . sizeof ( PVOID ), windef . PAGE_EXECUTE_READWRITE ):
+ IATentry . value = 0x42424242
+
+
+
+
+
+
+
5.1.2. DisableWow64FsRedirection
+
+
+class windows.utils.DisableWow64FsRedirection[source]
+A context manager that disable the SysWow64 Filesystem Redirection
+if is_process_32_bits :
+ def pop_calc_64 ():
+ with windows . utils . DisableWow64FsRedirection ():
+ return windows . utils . create_process ( r"C:\Windows\system32\calc.exe" , True )
+
+
+
+
+
+
+
+
5.2. Helper functions
+
+
+windows.utils.enable_privilege( lpszPrivilege , bEnablePrivilege ) [source]
+Enable or disable a privilege:
+enable_privilege ( SE_DEBUG_NAME , True )
+
+
+
+
+
+
+windows.utils.check_is_elevated( ) [source]
+Return True if process is Admin
+
+
+
+
+windows.utils.check_debug( ) [source]
+Check that kernel is in debug mode (beware of NOUMEX):
+https://msdn.microsoft.com/en-us/library/windows/hardware/ff556253(v=vs.85).aspx#_______noumex______
+
+
+
+
+windows.utils.create_process( path , args=None , dwCreationFlags=0 , show_windows=True ) [source]
+A convenient wrapper arround windows.winproxy.CreateProcessA()
+
+
+
+
+windows.utils.create_console( ) [source]
+Create a new console displaying STDOUT.
+Useful in injection of GUI process
+
+
+
+
+windows.utils.pop_shell( ) [source]
+Pop a console with an InterativeConsole
+
+
+
+
+windows.utils.create_file_from_handle( handle , mode='r' ) [source]
+Return a Python file around a Windows HANDLE
+
+
+
+
+windows.utils.get_handle_from_file( f ) [source]
+Get the Windows HANDLE of a python file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/various.html b/docs/build/html/various.html
new file mode 100644
index 0000000..7b7f3a5
--- /dev/null
+++ b/docs/build/html/various.html
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
+ 2. The windows objects — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2. The windows objects
+
Through the system object many classes representing various Windows
+parts are accessible.
+
This sections describes them by group of relation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/volume.html b/docs/build/html/volume.html
new file mode 100644
index 0000000..fa4cca8
--- /dev/null
+++ b/docs/build/html/volume.html
@@ -0,0 +1,180 @@
+
+
+
+
+
+
+
+ 2.8. Volume – The logical drives — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2.8. Volume – The logical drives
+
+
+
+class windows.winobject.volume.LogicalDrive( name ) [source]
+
+
+name
+Name of the logical drive
+
+
+
+
+
+path
+The target path of the device
+
+
+
+
+
+type
+The type of drive, values are:
+
+
+DRIVE_UNKNOWN(0x0L)
+DRIVE_NO_ROOT_DIR(0x1L)
+DRIVE_REMOVABLE(0x2L)
+DRIVE_FIXED(0x3L)
+DRIVE_REMOTE(0x4L)
+DRIVE_CDROM(0x5L)
+DRIVE_RAMDISK(0x6L)
+
+
+
+
+
+
+Type: long or int (or subclass)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/windows.html b/docs/build/html/windows.html
new file mode 100644
index 0000000..b82a6a9
--- /dev/null
+++ b/docs/build/html/windows.html
@@ -0,0 +1,351 @@
+
+
+
+
+
+
+
+ 1. The windows module — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
1. The windows module
+
The windows module is the module installed by setup.py .
+
This module exports some objects representing the current state of the system.
+It also offers some submodules aimed to help the interfacing with Windows and native code execution.
+
+The defaults objects accessible in windows are:
+
+
+The submodules that you might use by themself are:
+
+
+
+
+
1.1. The system object
+
+
+
+class windows.winobject.system.System[source]
+The state of the current Windows system Python is running on
+
+
+bitness
+The bitness of the system
+
+
+
+
+Type: int – 32 or 64
+
+
+
+
+
+
+
+computer_name
+The name of the computer
+
+
+
+
+
+handles
+The list of system handles
+
+
+
+
+
+logicaldrives
+List of logical drives [C:, ...]
+
+
+
+
+
+network = <windows.winobject.network.Network object at 0x04A61CF0>
+Object of class windows.winobject.network.Network
+
+
+
+
+processes
+The list of running processes
+
+
+
+
+
+product_type
+The product type, value might be:
+
+
+VER_NT_WORKSTATION(0x1L)
+VER_NT_DOMAIN_CONTROLLER(0x2L)
+VER_NT_SERVER(0x3L)
+
+
+
+
+
+
+Type: long or int (or subclass)
+
+
+
+
+
+
+
+registry = <windows.winobject.registry.Registry object at 0x04A61D10>
+Object of class windows.winobject.registry.Registry
+
+
+
+
+services
+The list of services
+
+
+
+
+
+threads
+The list of running threads
+
+
+
+
+
+version
+The version of the system
+
+
+
+
+Type: (int , int ) – (Major, Minor)
+
+
+
+
+
+
+
+version_name
+The name of the system version, values are:
+
+
+Windows Server 2016
+Windows 10
+Windows Server 2012 R2
+Windows 8.1
+Windows Server 2012
+Windows 8
+Windows Server 2008
+Windows 7
+Windows Server 2008
+Windows Vista
+Windows XP Professional x64 Edition
+TODO: version (5.2) + is_workstation + bitness == 32 (don’t even know if possible..)
+Windows Server 2003 R2
+Windows Server 2003
+Windows XP
+Windows 2000
+“Unknow Windows <version={0} | is_workstation={1}>”.format(version, is_workstation)
+
+
+
+
+
+
+
+wmi
+An object to perform wmi request to “root\cimv2”
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/winproxy.html b/docs/build/html/winproxy.html
new file mode 100644
index 0000000..e07570b
--- /dev/null
+++ b/docs/build/html/winproxy.html
@@ -0,0 +1,1063 @@
+
+
+
+
+
+
+
+ 4. windows.winproxy – Windows API — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
4. windows.winproxy – Windows API
+
windows.winproxy tries to be a pythontic wrapper around windows API of various DLL.
+It also heavily relies on ctypes and windows.generated_def.winfuncs
+
+Here are the things to know about windows.winproxy
+
+All of this is based on windows.generated_def.winfuncs
+DLL is loaded the first time an API of it is called
+All parameters can be passed by ordinal or keyword
+The call will fail if an argument with default value NeededParamater have been called without another value.
+The call will raise a subclass of WindowsError if it fails.
+Some functions are ‘transparent proxy’ it means that all parameters are mandatory
+
+
+
+
+
4.1. Example: VirtualAlloc
+
Exemple with the function VirtualAlloc in windows.winproxy
+
Documentation:
+
import windows
+windows . winproxy . VirtualAlloc
+# <function VirtualAlloc at 0x02ED63F0>
+
+help ( windows . winproxy . VirtualAlloc )
+# Help on function VirtualAlloc in module windows.winproxy:
+# VirtualAlloc(lpAddress=0, dwSize=NeededParameter, flAllocationType=MEM_COMMIT(0x1000L), flProtect=PAGE_EXECUTE_READWRITE(0x40L))
+# Errcheck:
+# raise Kernel32Error if result is 0
+
+
+
Calling it
+
import windows
+
+# Ordinal arguments
+windows . winproxy . VirtualAlloc ( 0 , 0x1000 )
+34537472
+
+# Keyword arguments
+windows . winproxy . VirtualAlloc ( dwSize = 0x1000 )
+34603008
+
+# NeededParameter must be provided
+windows . winproxy . VirtualAlloc ()
+"""
+Traceback (most recent call last):
+File "<stdin>", line 1, in <module>
+File "windows\winproxy.py", line 264, in VirtualAlloc
+ return VirtualAlloc.ctypes_function(lpAddress, dwSize, flAllocationType, flProtect)
+File "windows\winproxy.py", line 130, in perform_call
+ raise TypeError("{0}: Missing Mandatory parameter <{1}>".format(self.func_name, param_name))
+TypeError: VirtualAlloc: Missing Mandatory parameter <dwSize>
+"""
+
+# Error raises exception
+windows . winproxy . VirtualAlloc ( dwSize = 0xffffffff )
+"""
+Traceback (most recent call last):
+File "<stdin>", line 1, in <module>
+File "windows\winproxy.py", line 264, in VirtualAlloc
+ return VirtualAlloc.ctypes_function(lpAddress, dwSize, flAllocationType, flProtect)
+File "windows\winproxy.py", line 133, in perform_call
+ return self._cprototyped(*args)
+File "windows\winproxy.py", line 59, in kernel32_error_check
+ raise Kernel32Error(func_name)
+windows.winproxy.Kernel32Error: VirtualAlloc: [Error 8] Not enough storage is available to process this command.
+"""
+
+
+
+
+
+
Transparent proxies:
+
+AllocConsole()
+CloseHandle(hObject)
+ContinueDebugEvent(dwProcessId, dwThreadId, dwContinueStatus)
+DebugActiveProcess(dwProcessId)
+DebugActiveProcessStop(dwProcessId)
+DebugBreak()
+DebugBreakProcess(Process)
+DebugSetProcessKillOnExit(KillOnExit)
+EnumWindows(lpEnumFunc, lParam)
+ExitProcess(uExitCode)
+ExitThread(dwExitCode)
+FreeConsole()
+GetComputerNameA(lpBuffer, lpnSize)
+GetComputerNameW(lpBuffer, lpnSize)
+GetCurrentProcess()
+GetCurrentProcessorNumber()
+GetCurrentThread()
+GetCurrentThreadId()
+GetDriveTypeA(lpRootPathName)
+GetDriveTypeW(lpRootPathName)
+GetExitCodeProcess(hProcess, lpExitCode)
+GetExitCodeThread(hThread, lpExitCode)
+GetLastError()
+GetLogicalDriveStringsA(nBufferLength, lpBuffer)
+GetLogicalDriveStringsW(nBufferLength, lpBuffer)
+GetProcAddress(hModule, lpProcName)
+GetProcessId(Process)
+GetSidSubAuthority(pSid, nSubAuthority)
+GetSidSubAuthorityCount(pSid)
+GetStdHandle(nStdHandle)
+GetSystemMetrics(nIndex)
+GetThreadId(Thread)
+GetVersionExA(lpVersionInformation)
+GetVersionExW(lpVersionInformation)
+GetVolumeNameForVolumeMountPointA(lpszVolumeMountPoint, lpszVolumeName, cchBufferLength)
+GetVolumeNameForVolumeMountPointW(lpszVolumeMountPoint, lpszVolumeName, cchBufferLength)
+GetWindowModuleFileNameA(hwnd, pszFileName, cchFileNameMax)
+GetWindowModuleFileNameW(hwnd, pszFileName, cchFileNameMax)
+GetWindowTextA(hWnd, lpString, nMaxCount)
+GetWindowTextW(hWnd, lpString, nMaxCount)
+LoadLibraryA(lpFileName)
+LoadLibraryW(lpFileName)
+QueryDosDeviceA(lpDeviceName, lpTargetPath, ucchMax)
+QueryDosDeviceW(lpDeviceName, lpTargetPath, ucchMax)
+ResumeThread(hThread)
+SetStdHandle(nStdHandle, hHandle)
+SetTcpEntry(pTcpRow)
+SuspendThread(hThread)
+TerminateProcess(hProcess, uExitCode)
+TerminateThread(hThread, dwExitCode)
+VirtualQueryEx(hProcess, lpAddress, lpBuffer, dwLength)
+Wow64DisableWow64FsRedirection(OldValue)
+Wow64EnableWow64FsRedirection(Wow64FsEnableRedirection)
+Wow64GetThreadContext(hThread, lpContext)
+Wow64RevertWow64FsRedirection(OldValue)
+lstrcmpA(lpString1, lpString2)
+lstrcmpW(lpString1, lpString2)
+
+
Functions:
+
+AddVectoredContinueHandler:
+AddVectoredContinueHandler ( FirstHandler = 1 , VectoredHandler = NeededParameter )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+AddVectoredExceptionHandler:
+AddVectoredExceptionHandler ( FirstHandler = 1 , VectoredHandler = NeededParameter )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+AdjustTokenPrivileges:
+AdjustTokenPrivileges ( TokenHandle , DisableAllPrivileges = False , NewState = NeededParameter , BufferLength = None , PreviousState = None , ReturnLength = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+AlpcGetMessageAttribute:
+AlpcGetMessageAttribute ( Buffer , AttributeFlag )
+Errcheck :
+ Nothing special
+
+
+
+AlpcInitializeMessageAttribute:
+AlpcInitializeMessageAttribute ( AttributeFlags , Buffer , BufferSize , RequiredBufferSize )
+
+
+
+CoCreateInstance:
+CoCreateInstance ( rclsid , pUnkOuter = None , dwClsContext = tagCLSCTX . CLSCTX_INPROC_SERVER ( 0x1 L ), riid = NeededParameter , ppv = NeededParameter )
+Errcheck :
+ Nothing special
+
+
+
+CoInitializeEx:
+CoInitializeEx ( pvReserved = None , dwCoInit = tagCOINIT . COINIT_MULTITHREADED ( 0x0 L ))
+Errcheck :
+ Nothing special
+
+
+
+CoInitializeSecurity:
+CoInitializeSecurity ( pSecDesc , cAuthSvc , asAuthSvc , pReserved1 , dwAuthnLevel , dwImpLevel , pAuthList , dwCapabilities , pReserved3 )
+Errcheck :
+ Nothing special
+
+
+
+CreateFileA:
+CreateFileA ( lpFileName , dwDesiredAccess = GENERIC_READ ( 0x80000000 L ), dwShareMode = 0 , lpSecurityAttributes = None , dwCreationDisposition = OPEN_EXISTING ( 0x3 L ), dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL ( 0x80 L ), hTemplateFile = None )
+Errcheck :
+ raise Kernel32Error if result is NOT 0
+
+
+
+CreateFileMappingA:
+CreateFileMappingA ( hFile , lpFileMappingAttributes = None , flProtect = PAGE_READWRITE ( 0x4 L ), dwMaximumSizeHigh = 0 , dwMaximumSizeLow = NeededParameter , lpName = NeededParameter )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+CreateFileMappingW:
+CreateFileMappingW ( hFile , lpFileMappingAttributes = None , flProtect = PAGE_READWRITE ( 0x4 L ), dwMaximumSizeHigh = 0 , dwMaximumSizeLow = 0 , lpName = NeededParameter )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+CreateFileW:
+CreateFileW ( lpFileName , dwDesiredAccess = GENERIC_READ ( 0x80000000 L ), dwShareMode = 0 , lpSecurityAttributes = None , dwCreationDisposition = OPEN_EXISTING ( 0x3 L ), dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL ( 0x80 L ), hTemplateFile = None )
+Errcheck :
+ raise Kernel32Error if result is NOT 0
+
+
+
+CreateProcessA:
+CreateProcessA ( lpApplicationName , lpCommandLine = None , lpProcessAttributes = None , lpThreadAttributes = None , bInheritHandles = False , dwCreationFlags = 0 , lpEnvironment = None , lpCurrentDirectory = None , lpStartupInfo = None , lpProcessInformation = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+CreateProcessW:
+CreateProcessW ( lpApplicationName , lpCommandLine = None , lpProcessAttributes = None , lpThreadAttributes = None , bInheritHandles = False , dwCreationFlags = 0 , lpEnvironment = None , lpCurrentDirectory = None , lpStartupInfo = None , lpProcessInformation = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+CreateRemoteThread:
+CreateRemoteThread ( hProcess = NeededParameter , lpThreadAttributes = None , dwStackSize = 0 , lpStartAddress = NeededParameter , lpParameter = NeededParameter , dwCreationFlags = 0 , lpThreadId = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+CreateThread:
+CreateThread ( lpThreadAttributes = None , dwStackSize = 0 , lpStartAddress = NeededParameter , lpParameter = NeededParameter , dwCreationFlags = 0 , lpThreadId = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+CreateToolhelp32Snapshot:
+CreateToolhelp32Snapshot ( dwFlags , th32ProcessID = 0 )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+CryptCATAdminAcquireContext:
+CryptCATAdminAcquireContext ( phCatAdmin , pgSubsystem , dwFlags )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+CryptCATAdminCalcHashFromFileHandle:
+CryptCATAdminCalcHashFromFileHandle ( hFile , pcbHash , pbHash , dwFlags )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+CryptCATAdminEnumCatalogFromHash:
+CryptCATAdminEnumCatalogFromHash ( hCatAdmin , pbHash , cbHash , dwFlags , phPrevCatInfo )
+Errcheck :
+ Nothing special
+
+
+
+CryptCATAdminReleaseCatalogContext:
+CryptCATAdminReleaseCatalogContext ( hCatAdmin , hCatInfo , dwFlags )
+Errcheck :
+ Nothing special
+
+
+
+CryptCATAdminReleaseContext:
+CryptCATAdminReleaseContext ( hCatAdmin , dwFlags )
+Errcheck :
+ Nothing special
+
+
+
+CryptCATCatalogInfoFromContext:
+CryptCATCatalogInfoFromContext ( hCatInfo , psCatInfo , dwFlags )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+DeviceIoControl:
+DeviceIoControl ( hDevice , dwIoControlCode , lpInBuffer , nInBufferSize = None , lpOutBuffer = NeededParameter , nOutBufferSize = None , lpBytesReturned = None , lpOverlapped = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+DuplicateHandle:
+DuplicateHandle ( hSourceProcessHandle , hSourceHandle , hTargetProcessHandle , lpTargetHandle , dwDesiredAccess = 0 , bInheritHandle = False , dwOptions = 0 )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+EnumServicesStatusExA:
+EnumServicesStatusExA ( hSCManager , InfoLevel , dwServiceType , dwServiceState , lpServices , cbBufSize , pcbBytesNeeded , lpServicesReturned , lpResumeHandle , pszGroupName )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+EnumServicesStatusExW:
+EnumServicesStatusExW ( hSCManager , InfoLevel , dwServiceType , dwServiceState , lpServices , cbBufSize , pcbBytesNeeded , lpServicesReturned , lpResumeHandle , pszGroupName )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetExtendedTcpTable:
+GetExtendedTcpTable ( pTcpTable , pdwSize = None , bOrder = True , ulAf = NeededParameter , TableClass = _TCP_TABLE_CLASS . TCP_TABLE_OWNER_PID_ALL ( 0x5 L ), Reserved = 0 )
+Errcheck :
+ raise IphlpapiError if result is NOT 0
+
+
+
+GetFileVersionInfoA:
+GetFileVersionInfoA ( lptstrFilename , dwHandle = 0 , dwLen = None , lpData = NeededParameter )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetFileVersionInfoSizeA:
+GetFileVersionInfoSizeA ( lptstrFilename , lpdwHandle = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetFileVersionInfoSizeW:
+GetFileVersionInfoSizeW ( lptstrFilename , lpdwHandle = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetFileVersionInfoW:
+GetFileVersionInfoW ( lptstrFilename , dwHandle = 0 , dwLen = None , lpData = NeededParameter )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetIfTable:
+GetIfTable ( pIfTable , pdwSize , bOrder = False )
+Errcheck :
+ raise IphlpapiError if result is NOT 0
+
+
+
+GetInterfaceInfo:
+GetInterfaceInfo ( pIfTable , dwOutBufLen = None )
+Errcheck :
+ raise IphlpapiError if result is NOT 0
+
+
+
+GetIpAddrTable:
+GetIpAddrTable ( pIpAddrTable , pdwSize , bOrder = False )
+Errcheck :
+ raise IphlpapiError if result is NOT 0
+
+
+
+GetMappedFileNameAWrapper:
+GetMappedFileNameAWrapper ( hProcess , lpv , lpFilename , nSize = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetMappedFileNameAWrapper:
+GetMappedFileNameAWrapper ( hProcess , lpv , lpFilename , nSize = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetMappedFileNameWWrapper:
+GetMappedFileNameWWrapper ( hProcess , lpv , lpFilename , nSize = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetMappedFileNameWWrapper:
+GetMappedFileNameWWrapper ( hProcess , lpv , lpFilename , nSize = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetModuleBaseNameAWrapper:
+GetModuleBaseNameAWrapper ( hProcess , hModule , lpBaseName , nSize = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetModuleBaseNameAWrapper:
+GetModuleBaseNameAWrapper ( hProcess , hModule , lpBaseName , nSize = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetModuleBaseNameWWrapper:
+GetModuleBaseNameWWrapper ( hProcess , hModule , lpBaseName , nSize = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetModuleBaseNameWWrapper:
+GetModuleBaseNameWWrapper ( hProcess , hModule , lpBaseName , nSize = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetProcessImageFileNameAWrapper:
+GetProcessImageFileNameAWrapper ( hProcess , lpImageFileName , nSize = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetProcessImageFileNameAWrapper:
+GetProcessImageFileNameAWrapper ( hProcess , lpImageFileName , nSize = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetProcessImageFileNameWWrapper:
+GetProcessImageFileNameWWrapper ( hProcess , lpImageFileName , nSize = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetProcessImageFileNameWWrapper:
+GetProcessImageFileNameWWrapper ( hProcess , lpImageFileName , nSize = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetProcessTimes:
+GetProcessTimes ( hProcess , lpCreationTime , lpExitTime , lpKernelTime , lpUserTime )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetThreadContext:
+GetThreadContext ( hThread , lpContext = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetTokenInformation:
+GetTokenInformation ( TokenHandle = NeededParameter , TokenInformationClass = NeededParameter , TokenInformation = None , TokenInformationLength = 0 , ReturnLength = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetVolumeInformationA:
+GetVolumeInformationA ( lpRootPathName , lpVolumeNameBuffer , nVolumeNameSize , lpVolumeSerialNumber , lpMaximumComponentLength , lpFileSystemFlags , lpFileSystemNameBuffer , nFileSystemNameSize )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+GetVolumeInformationW:
+GetVolumeInformationW ( lpRootPathName , lpVolumeNameBuffer = None , nVolumeNameSize = 0 , lpVolumeSerialNumber = None , lpMaximumComponentLength = None , lpFileSystemFlags = None , lpFileSystemNameBuffer = None , nFileSystemNameSize = 0 )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+LdrLoadDll:
+LdrLoadDll ( PathToFile , Flags , ModuleFileName , ModuleHandle )
+
+
+
+LookupAccountSidA:
+LookupAccountSidA ( lpSystemName , lpSid , lpName , cchName , lpReferencedDomainName , cchReferencedDomainName , peUse )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+LookupAccountSidW:
+LookupAccountSidW ( lpSystemName , lpSid , lpName , cchName , lpReferencedDomainName , cchReferencedDomainName , peUse )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+LookupPrivilegeValueA:
+LookupPrivilegeValueA ( lpSystemName = None , lpName = NeededParameter , lpLuid = NeededParameter )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+LookupPrivilegeValueW:
+LookupPrivilegeValueW ( lpSystemName = None , lpName = NeededParameter , lpLuid = NeededParameter )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+MapViewOfFile:
+MapViewOfFile ( hFileMappingObject , dwDesiredAccess = FILE_MAP_ALL_ACCESS ( 0xf001f L ), dwFileOffsetHigh = 0 , dwFileOffsetLow = 0 , dwNumberOfBytesToMap = NeededParameter )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+NtAlpcAcceptConnectPort:
+NtAlpcAcceptConnectPort ( PortHandle , ConnectionPortHandle , Flags , ObjectAttributes , PortAttributes , PortContext , ConnectionRequest , ConnectionMessageAttributes , AcceptConnection )
+
+
+
+NtAlpcConnectPort:
+NtAlpcConnectPort ( PortHandle , PortName , ObjectAttributes , PortAttributes , Flags , RequiredServerSid , ConnectionMessage , BufferLength , OutMessageAttributes , InMessageAttributes , Timeout )
+
+
+
+NtAlpcCreatePort:
+NtAlpcCreatePort ( PortHandle , ObjectAttributes , PortAttributes )
+
+
+
+NtAlpcSendWaitReceivePort:
+NtAlpcSendWaitReceivePort ( PortHandle , Flags , SendMessage , SendMessageAttributes , ReceiveMessage , BufferLength , ReceiveMessageAttributes , Timeout )
+
+
+
+NtCreateThreadEx:
+NtCreateThreadEx ( ThreadHandle = None , DesiredAccess = 2097151 , ObjectAttributes = 0 , ProcessHandle = NeededParameter , lpStartAddress = NeededParameter , lpParameter = NeededParameter , CreateSuspended = 0 , dwStackSize = 0 , Unknown1 = 0 , Unknown2 = 0 , Unknown = 0 )
+
+
+
+NtGetContextThread:
+NtGetContextThread ( hThread , lpContext )
+
+
+
+NtOpenDirectoryObject:
+NtOpenDirectoryObject ( DirectoryHandle , DesiredAccess , ObjectAttributes )
+
+
+
+NtOpenEvent:
+NtOpenEvent ( EventHandle , DesiredAccess , ObjectAttributes )
+
+
+
+NtOpenSymbolicLinkObject:
+NtOpenSymbolicLinkObject ( LinkHandle , DesiredAccess , ObjectAttributes )
+
+
+
+NtProtectVirtualMemory:
+NtProtectVirtualMemory ( ProcessHandle , BaseAddress , NumberOfBytesToProtect , NewAccessProtection , OldAccessProtection = None )
+
+
+
+NtQueryDirectoryObject:
+NtQueryDirectoryObject ( DirectoryHandle , Buffer , Length , ReturnSingleEntry , RestartScan , Context , ReturnLength )
+
+
+
+NtQueryInformationProcess:
+NtQueryInformationProcess ( ProcessHandle , ProcessInformationClass , ProcessInformation , ProcessInformationLength = 0 , ReturnLength = None )
+
+
+
+NtQueryInformationThread:
+NtQueryInformationThread ( ThreadHandle , ThreadInformationClass , ThreadInformation , ThreadInformationLength = 0 , ReturnLength = None )
+
+
+
+NtQueryObject:
+NtQueryObject ( Handle , ObjectInformationClass , ObjectInformation = None , ObjectInformationLength = 0 , ReturnLength = NeededParameter )
+
+
+
+NtQuerySymbolicLinkObject:
+NtQuerySymbolicLinkObject ( LinkHandle , LinkTarget , ReturnedLength )
+
+
+
+NtQuerySystemInformation:
+NtQuerySystemInformation ( SystemInformationClass , SystemInformation = None , SystemInformationLength = 0 , ReturnLength = NeededParameter )
+
+
+
+NtQueryVirtualMemory:
+NtQueryVirtualMemory ( ProcessHandle , BaseAddress , MemoryInformationClass , MemoryInformation = NeededParameter , MemoryInformationLength = 0 , ReturnLength = None )
+
+
+
+NtSetContextThread:
+NtSetContextThread ( hThread , lpContext )
+
+
+
+NtWow64ReadVirtualMemory64:
+NtWow64ReadVirtualMemory64 ( hProcess , lpBaseAddress , lpBuffer , nSize , lpNumberOfBytesRead = None )
+
+
+
+NtWow64WriteVirtualMemory64:
+NtWow64WriteVirtualMemory64 ( hProcess , lpBaseAddress , lpBuffer , nSize , lpNumberOfBytesWritten = None )
+
+
+
+OpenEventA:
+OpenEventA ( dwDesiredAccess , bInheritHandle , lpName )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+OpenEventW:
+OpenEventW ( dwDesiredAccess , bInheritHandle , lpName )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+OpenProcess:
+OpenProcess ( dwDesiredAccess = PROCESS_ALL_ACCESS ( 0x1f0fff L ), bInheritHandle = 0 , dwProcessId = NeededParameter )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+OpenProcessToken:
+OpenProcessToken ( ProcessHandle = None , DesiredAccess = NeededParameter , TokenHandle = NeededParameter )
+If ProcessHandle is None : take the current process
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+OpenSCManagerA:
+OpenSCManagerA ( lpMachineName = None , lpDatabaseName = None , dwDesiredAccess = SC_MANAGER_ALL_ACCESS ( 0xf003f L ))
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+OpenSCManagerW:
+OpenSCManagerW ( lpMachineName = None , lpDatabaseName = None , dwDesiredAccess = SC_MANAGER_ALL_ACCESS ( 0xf003f L ))
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+OpenThread:
+OpenThread ( dwDesiredAccess = THREAD_ALL_ACCESS ( 0x1f03ff L ), bInheritHandle = 0 , dwThreadId = NeededParameter )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+Process32First:
+Process32First ( hSnapshot , lpte )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+Process32Next:
+Process32Next ( hSnapshot , lpte )
+Errcheck :
+ Nothing special
+
+
+
+QueryWorkingSetWrapper:
+QueryWorkingSetWrapper ( hProcess , pv , cb )
+Errcheck :
+ raise Kernel32Error if result is 0
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+QueryWorkingSetExWrapper:
+QueryWorkingSetExWrapper ( hProcess , pv , cb )
+Errcheck :
+ raise Kernel32Error if result is 0
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+QueryWorkingSetExWrapper:
+QueryWorkingSetExWrapper ( hProcess , pv , cb )
+Errcheck :
+ raise Kernel32Error if result is 0
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+QueryWorkingSetWrapper:
+QueryWorkingSetWrapper ( hProcess , pv , cb )
+Errcheck :
+ raise Kernel32Error if result is 0
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+ReadProcessMemory:
+ReadProcessMemory ( hProcess , lpBaseAddress , lpBuffer , nSize , lpNumberOfBytesRead = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+RegCloseKey:
+RegCloseKey ( hKey )
+Errcheck :
+ raise Kernel32Error if result is NOT 0
+
+
+
+RegGetValueA:
+RegGetValueA ( hkey , lpSubKey , lpValue , dwFlags , pdwType , pvData , pcbData )
+Errcheck :
+ raise Kernel32Error if result is NOT 0
+
+
+
+RegGetValueW:
+RegGetValueW ( hkey , lpSubKey = None , lpValue = NeededParameter , dwFlags = 0 , pdwType = None , pvData = None , pcbData = None )
+Errcheck :
+ raise Kernel32Error if result is NOT 0
+
+
+
+RegOpenKeyExA:
+RegOpenKeyExA ( hKey , lpSubKey , ulOptions , samDesired , phkResult )
+Errcheck :
+ raise Kernel32Error if result is NOT 0
+
+
+
+RegOpenKeyExW:
+RegOpenKeyExW ( hKey , lpSubKey , ulOptions , samDesired , phkResult )
+Errcheck :
+ raise Kernel32Error if result is NOT 0
+
+
+
+RemoveVectoredExceptionHandler:
+RemoveVectoredExceptionHandler ( Handler )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+SetThreadAffinityMask:
+SetThreadAffinityMask ( hThread = None , dwThreadAffinityMask = NeededParameter )
+If hThread is not given , it will be the current thread
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+SetThreadContext:
+SetThreadContext ( hThread , lpContext )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+Thread32First:
+Thread32First ( hSnapshot , lpte )
+Set byref ( lpte ) if needed
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+Thread32Next:
+Thread32Next ( hSnapshot , lpte )
+Set byref ( lpte ) if needed
+Errcheck :
+ Nothing special
+
+
+
+VerQueryValueA:
+VerQueryValueA ( pBlock , lpSubBlock , lplpBuffer , puLen )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+VerQueryValueW:
+VerQueryValueW ( pBlock , lpSubBlock , lplpBuffer , puLen )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+VirtualAlloc:
+VirtualAlloc ( lpAddress = 0 , dwSize = NeededParameter , flAllocationType = MEM_COMMIT ( 0x1000 L ), flProtect = PAGE_EXECUTE_READWRITE ( 0x40 L ))
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+VirtualAllocEx:
+VirtualAllocEx ( hProcess , lpAddress = 0 , dwSize = NeededParameter , flAllocationType = MEM_COMMIT ( 0x1000 L ), flProtect = PAGE_EXECUTE_READWRITE ( 0x40 L ))
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+VirtualFree:
+VirtualFree ( lpAddress , dwSize = 0 , dwFreeType = MEM_RELEASE ( 0x8000 L ))
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+VirtualFreeEx:
+VirtualFreeEx ( hProcess , lpAddress , dwSize = 0 , dwFreeType = MEM_RELEASE ( 0x8000 L ))
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+VirtualProtect:
+VirtualProtect ( lpAddress , dwSize , flNewProtect , lpflOldProtect = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+VirtualProtectEx:
+VirtualProtectEx ( hProcess , lpAddress , dwSize , flNewProtect , lpflOldProtect = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+WaitForDebugEvent:
+WaitForDebugEvent ( lpDebugEvent , dwMilliseconds = INFINITE ( 0xffffffff L ))
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+WaitForSingleObject:
+WaitForSingleObject ( hHandle , dwMilliseconds = INFINITE ( 0xffffffff L ))
+Errcheck :
+ raise Kernel32Error if result is NOT 0
+
+
+
+WinVerifyTrust:
+WinVerifyTrust ( hwnd , pgActionID , pWVTData )
+Errcheck :
+ Nothing special
+
+
+
+Wow64SetThreadContext:
+Wow64SetThreadContext ( hThread , lpContext )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+WriteFile:
+WriteFile ( hFile , lpBuffer , nNumberOfBytesToWrite = None , lpNumberOfBytesWritten = None , lpOverlapped = None )
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+WriteProcessMemory:
+WriteProcessMemory ( hProcess , lpBaseAddress , lpBuffer , nSize = None , lpNumberOfBytesWritten = None )
+Computer nSize with len ( lpBuffer ) if not given
+Errcheck :
+ raise Kernel32Error if result is 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/wintrust.html b/docs/build/html/wintrust.html
new file mode 100644
index 0000000..6516642
--- /dev/null
+++ b/docs/build/html/wintrust.html
@@ -0,0 +1,236 @@
+
+
+
+
+
+
+
+ 6. windows.wintrust – Checking signature — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
6. windows.wintrust – Checking signature
+
+
The wintrust module offers wrapper around wintrust.dll .
+It allows to check the signature of a file.
+
The signature of a file can be at two differents place:
+
+
+
+
+
6.1. API
+
+
+windows.wintrust.is_signed( filename ) [source]
+Check if filename is signed:
+
+
+File embeds a valid signature
+File is part of a signed catalog file
+
+
+
+
+
+
+Returns: bool
+
+
+
+
+
+
+
+windows.wintrust.full_signature_information( filename ) [source]
+Returns more information about the signature of filename
+
+
+
+
+
+windows.wintrust.check_signature( filename ) [source]
+Check if filename embeds a valid signature.
+
+
+
+
+Returns: int : 0 if filename have a valid signature else the error
+
+
+
+
+
+
+
6.1.1. SignatureData
+
+
+class windows.wintrust.SignatureData( signed , catalog , catalogsigned , additionalinfo )
+Signature information for FILENAME :
+
+
+signed : True if FILENAME embeds a valide signature
+catalog : The filename of the catalog FILENAME is part of (if any)
+catalogsigned : True if catalog embeds a valide signature
+additionalinfo : The return error of check_signature(FILENAME)
+
+
+additionalinfo is useful to know if FILENAME signature was rejected for an invalid root / expired cert.
+
+
+additionalinfo
+Alias for field number 3
+
+
+
+
+catalog
+Alias for field number 1
+
+
+
+
+catalogsigned
+Alias for field number 2
+
+
+
+
+signed
+Alias for field number 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/wip.html b/docs/build/html/wip.html
new file mode 100644
index 0000000..ffe3b2d
--- /dev/null
+++ b/docs/build/html/wip.html
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+ 10. Early Work In Progress — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
10. Early Work In Progress
+
Here are some features that are still work in progress. Code might be unstable and/or ultra-ugly.
+
<Nothing right now>
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/wmi.html b/docs/build/html/wmi.html
new file mode 100644
index 0000000..ff9c88c
--- /dev/null
+++ b/docs/build/html/wmi.html
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+ 2.9. WMI – Make request to WMI — PythonForWindows 0.2 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2.9. WMI – Make request to WMI
+
+
+
+class windows.winobject.wmi.WmiRequester( target='root\cimv2' , user=None , password=None ) [source]
+An object to perform wmi request to root\cimv2
+
+
+select( frm , attrs='*' ) [source]
+Select attrs from frm
+
+
+
+
+Return type: list of dict
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/doc/generate_winproxy_list.py b/docs/generate_winproxy_list.py
similarity index 100%
rename from doc/generate_winproxy_list.py
rename to docs/generate_winproxy_list.py
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 0000000..44c04e3
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,9 @@
+
+
+Redirection to build/html
+
+
+
+Nothing here.
+
+
\ No newline at end of file
diff --git a/doc/make.bat b/docs/make.bat
similarity index 100%
rename from doc/make.bat
rename to docs/make.bat
diff --git a/docs/source/com.rst b/docs/source/com.rst
new file mode 100644
index 0000000..307bcf2
--- /dev/null
+++ b/docs/source/com.rst
@@ -0,0 +1,43 @@
+:mod:`windows.com` - Component Object Model
+""""""""""""""""""""""""""""""""""""""""""""
+
+.. module:: windows.com
+
+A module to call `COM` interfaces from `Python` or
+`COM` vtable in python.
+
+This code is only used in :mod:`windows.winobject.wmi` and :mod:`windows.winobject.network` for the firewall.
+The ability to create `COM` vtable is used in the `LKD project `_ .
+
+
+Using a COM interface
+'''''''''''''''''''''
+
+It's possible to directly call `COM` interface from python. All you need is the definition of the `COM` interface.
+
+There are three ways to get the definition of the code interface:
+
+ * By using it from :mod:`windows.generated_def.interfaces`
+ * By writing it yourself : `_
+ * By generating it.
+
+To generate a `COM` interface you need its definition from the ".c" file.
+Then add thisit to ``PythonForWindows\ctypes_generation\com\MyInterface.txt``.
+Finally re-generate the interface using ``generate.py``.
+
+When you have the `COM` interface defintion you can create an instance of it.
+Then you need to retrieve the interface by using an API returning an object or :func:`window.com.create_instance`.
+You can then use the instance to call whatever method you need.
+
+.. note::
+
+ see sample :ref:`sample_com_firewall`
+
+Implementing a COM interface
+''''''''''''''''''''''''''''
+
+To create `COM` object you need to:
+
+ 1. Describe your ComVtable `CODE1 `_
+ 2. Implement the python functions described `CODE2 `_
+ 3. Create an instance and pass it to whatever native function expects it `CODE3 `_
\ No newline at end of file
diff --git a/doc/source/conf.py b/docs/source/conf.py
similarity index 100%
rename from doc/source/conf.py
rename to docs/source/conf.py
diff --git a/docs/source/debug.rst b/docs/source/debug.rst
new file mode 100644
index 0000000..4c5c05a
--- /dev/null
+++ b/docs/source/debug.rst
@@ -0,0 +1,88 @@
+:mod:`windows.debug` -- Debugging
+=================================
+
+.. module:: windows.debug
+
+.. note::
+
+ See sample :ref:`sample_debugger`
+
+:class:`Debugger`
+"""""""""""""""""
+
+The :class:`Debugger` is the base class to perform the debugging of a remote process.
+The :class:`Debugger` have some functions called on given event that can be implemented by subclasses.
+
+All Memory-breakpoint are disabled when callind a public callback or a breakpoint ``trigger()`` function.
+
+This means that those methods see the original ``current_process`` memory access rights.
+
+.. autoclass:: Debugger
+ :members:
+ :member-order: bysource
+
+ .. automethod:: __init__
+
+
+
+:class:`LocalDebugger`
+""""""""""""""""""""""
+
+.. note::
+
+ See sample :ref:`sample_local_debugger`
+
+The :class:`Debugger` is the base class to perform the debugging the current process.
+It is based on :func:`VectoredException` (see :ref:`sample_vectoredexception`)
+
+There is not much documentation for now as the code might change soon.
+
+
+
+.. autoclass:: LocalDebugger
+ :members:
+
+
+
+:class:`Breakpoint`
+"""""""""""""""""""
+
+Standard breakpoints types expect an address as argument.
+
+An address can be:
+
+ * An :class:`int`
+ * A :class:`str` of form (breakpoint will be put when ``DLL`` is loaded):
+
+ * ``"DLL!ApiName"``
+ * ``"DLL!Offset"`` where offset is a int ("16", "0x10", ..)
+
+
+When a breakpoint is hit, its ``trigger`` function is called with the debugger and a
+``DEBUG_EXECEPTION_EVENT`` structure as argument.
+
+
+.. autoclass:: Breakpoint
+ :members:
+
+.. autoclass:: HXBreakpoint
+ :members:
+ :inherited-members:
+
+.. autoclass:: MemoryBreakpoint
+ :members:
+ :inherited-members:
+ :special-members: __init__
+
+
+
+.. note::
+
+ MemoryBreakpoint are triggered based on the fault address only (as I don't know a way to get the size of the read/write causing the fault without embedding a disassembler).
+
+ This means that a MEMBP at address ``X`` won't be triggered by a write of size 4 at address ``X - 1``. it's sad I know.
+
+.. autoclass:: FunctionBP
+ :members:
+ :inherited-members:
+ :special-members: __init__
\ No newline at end of file
diff --git a/docs/source/exception.rst b/docs/source/exception.rst
new file mode 100644
index 0000000..d0e9ac9
--- /dev/null
+++ b/docs/source/exception.rst
@@ -0,0 +1,99 @@
+Exception and Context related structures
+========================================
+
+.. module:: windows.winobject.exception
+
+
+This module regroups all the Exception/Context related structures and functions.
+Most of the structures are the Windows structure with a prefix ``E`` (For enhanced)
+
+Those structure have the same fields that the normal windows ones but their types might vary for a simpler use.
+
+
+This module also define the decorator :func:`VectoredException` which allows to play with ``Vectored Exception Handler`` in Python
+
+.. note::
+
+ See sample :ref:`sample_vectoredexception` samples
+
+Exception Records
+'''''''''''''''''
+
+.. autoclass:: EEXCEPTION_RECORD
+ :members:
+ :inherited-members:
+
+.. autoclass:: EEXCEPTION_RECORD32
+ :inherited-members:
+
+.. autoclass:: EEXCEPTION_RECORD64
+ :members:
+ :inherited-members:
+
+EXCEPTION DEBUG INFO
+''''''''''''''''''''
+
+.. autoclass:: EEXCEPTION_DEBUG_INFO32
+ :members:
+ :inherited-members:
+
+ .. data:: ExceptionRecord
+
+ :type: :class:`EEXCEPTION_RECORD32`
+
+
+.. autoclass:: EEXCEPTION_DEBUG_INFO64
+ :members:
+ :inherited-members:
+
+ .. data:: ExceptionRecord
+
+ :type: :class:`EEXCEPTION_RECORD64`
+
+Context
+'''''''
+
+.. autoclass:: ECONTEXT32
+ :members:
+ :inherited-members:
+
+.. autoclass:: ECONTEXTWOW64
+ :members:
+ :inherited-members:
+
+.. autoclass:: ECONTEXT64
+ :members:
+ :inherited-members:
+
+.. autoclass:: EEflags
+ :members:
+
+.. autoclass:: EDr7
+ :members:
+
+EXCEPTION POINTERS
+''''''''''''''''''
+
+.. autoclass:: EEXCEPTION_POINTERS
+ :members:
+
+ .. data:: ExceptionRecord
+
+ :type: POINTER to :class:`EEXCEPTION_RECORD`
+
+ .. data:: ContextRecord
+
+ :type: POINTER to :class:`ECONTEXT32` or :class:`ECONTEXT64`
+
+
+.. _vectoredexception:
+
+Vectored Exception
+''''''''''''''''''
+
+.. note::
+
+ See sample :ref:`sample_vectoredexception`
+
+.. autoclass:: VectoredException
+ :members:
\ No newline at end of file
diff --git a/docs/source/handle.rst b/docs/source/handle.rst
new file mode 100644
index 0000000..1497638
--- /dev/null
+++ b/docs/source/handle.rst
@@ -0,0 +1,10 @@
+Handle -- Processes handles
+============================
+
+.. note::
+
+ See sample :ref:`sample_system`
+
+.. module:: windows.winobject.handle
+
+.. autoclass:: Handle
\ No newline at end of file
diff --git a/docs/source/iat_hook.rst b/docs/source/iat_hook.rst
new file mode 100644
index 0000000..2f98d42
--- /dev/null
+++ b/docs/source/iat_hook.rst
@@ -0,0 +1,113 @@
+IAT hooking
+"""""""""""
+
+.. note::
+
+ See sample :ref:`sample_iat_hook`
+
+Putting an IAT hook
+'''''''''''''''''''
+
+To setup your IAT hook you just need:
+
+ * A callback that respect the :ref:`hook_protocol`
+ * The :class:`windows.pe_parse.IATEntry` to hook
+
+
+You just need to use the function :func:`windows.pe_parse.IATEntry.set_hook`
+
+Putting a hook::
+
+ import windows
+ from windows.hooks import *
+
+ @CreateFileACallback
+ def createfile_callback(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile, real_function):
+ print("Trying to open {0}".format(lpFileName))
+ if "secret" in lpFileName:
+ return 0xffffffff
+ return real_function()
+
+ my_exe = windows.current_process.peb.modules[0]
+ imp = my_exe.pe.imports
+
+ iat_create_file = [entry for entry in imp['kernel32.dll'] if entry.name == "CreateFileA"]
+ iat_create_file.set_hook(createfile_callback)
+
+
+.. _hook_protocol:
+
+Hook protocol
+'''''''''''''
+
+Callback arguments
+------------------
+
+A hook callback must have the same number of argument as the hooked API, PLUS a last argument ``real_function``.
+
+
+
+The ``real_function`` argument is a callable that represent the hooked API, it can be called in two ways:
+
+ * Without argument, the call will be done with the argument originaly passed to your callback. This allows simple redirection to the real API.
+
+ * With arguments it will simply call the API with these.
+
+Example::
+
+ def createfile_callback(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile, real_function):
+ print("Trying to open {0}".format(lpFileName))
+ if "secret" in lpFileName:
+ return 0xffffffff
+ # Perform the real call
+ return real_function()
+
+
+A hook callback must also embed some :ref:`Type Information `
+
+
+.. _type_information:
+
+Callback type information
+--------------------------
+
+In order make the magic behind hook callback, :mod:`ctypes` needs to have type information about the API parameters.
+
+There is (again) two ways to give those informations to your hook callback. Both techniques use a decorator to setup type information to the callback.
+
+ * Giving the type manualy using the decorator :class:`windows.hooks.Callback`::
+
+ from windows.hooks import *
+ # First type is return type, others are parameters types
+ @Callback(ctypes.c_void_p, ctypes.c_ulong)
+ def exit_callback(x, real_function):
+ print("Try to quit with {0} | {1}".format(x, type(x)))
+ if x == 3:
+ print("TRYING TO REAL EXIT")
+ return real_function(1234)
+ return 0x4242424243444546
+
+ * Using the `Callback` decorator generated from known functions::
+
+ from windows.hooks import *
+ # Decorator name is always API_NAME + "CallBack"
+ @CreateFileACallback
+ def createfile_callback(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile, real_function):
+ print("Trying to open {0}".format(lpFileName))
+ if "secret" in lpFileName:
+ return 0xffffffff
+ return real_function()
+
+ .. note::
+
+ See the list of known functions
+
+
+:mod:`windows.hooks`
+''''''''''''''''''''
+
+.. module:: windows.hooks
+
+.. autoclass:: windows.hooks.Callback
+
+.. autoclass:: windows.hooks.IATHook
\ No newline at end of file
diff --git a/docs/source/index.rst b/docs/source/index.rst
new file mode 100644
index 0000000..6246398
--- /dev/null
+++ b/docs/source/index.rst
@@ -0,0 +1,35 @@
+.. PyWindows documentation master file, created by
+ sphinx-quickstart on Tue Apr 07 11:39:41 2015.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to PythonForWindows's documentation!
+============================================
+
+Contents:
+
+.. toctree::
+ :maxdepth: 2
+ :numbered:
+
+ windows.rst
+ various.rst
+ native_exec.rst
+ winproxy.rst
+ utils.rst
+ wintrust.rst
+ debug.rst
+ com.rst
+ iat_hook.rst
+ wip.rst
+ internals.rst
+ sample.rst
+
+
+Indices and tables
+==================
+
+* :ref:`modindex`
+* :ref:`search`
+* :ref:`genindex`
+
diff --git a/docs/source/internals.rst b/docs/source/internals.rst
new file mode 100644
index 0000000..7163570
--- /dev/null
+++ b/docs/source/internals.rst
@@ -0,0 +1,125 @@
+Internals
+=========
+
+Because some horrible hacks of ``PythonForWindows`` are hidden and I wanted to talk about it.
+
+remotectypes.py
+'''''''''''''''
+
+.. module:: windows.remotectypes
+
+Performing parsing of PEB / PE in remote process may be painful and i didn't want
+to have two versions of all my parsing code.
+
+So I made a wrapper around :mod:`ctypes` that is able to do two things:
+
+ - Transform a 32bits ctypes structure into a 64bits one and reverse
+
+ This is done by replacing the ``c_void_p``/``c_char_p`` by ``DWORD`` or
+ ``QWORD`` and rewriting a wrapper around the :mod:`ctypes` ``POINTER`` and other stuff.
+ It might not works for every structure by i didn't have any problem for now.
+
+ - Read the memory in another process
+
+ For this one I rewrote a class that use the standard :mod:`ctypes` structure
+ offset-size calculation, extracts those information when asked for a field and read it from the target process.
+ We just need to take care of special cases: ``POINTER`` / ``ARRAY`` / ``STRING`` / ..
+
+We also need to be carreful about the inheritance, we need to inherit from "hidden"
+:class:`ctypes` classes to keep the magic working.
+
+
+This module exports the following API:
+
+.. autofunction:: transform_type_to_remote32bits
+
+.. autofunction:: transform_type_to_remote64bits
+
+Both functions return a class that represent the structure in a remote process.
+The class.__init__ accept two arguments:
+
+ * ``base_addr``: the address of the object in the remote process
+ * ``target``: an object with a method ``read_memory`` (so a :class:`windows.winobject.WinProcess` in our case)
+
+Example ``WinProcess.peb``::
+
+ def peb(self):
+ if windows.current_process.bitness == 32 and self.bitness == 64:
+ return RemotePEB64(self.peb_addr, self)
+ if windows.current_process.bitness == 64 and self.bitness == 32:
+ return RemotePEB32(self.peb_addr, self)
+ return RemotePEB(self.peb_addr, self)
+
+I am pretty sure that this code does NOT handle all the cases, so it might break some day.
+
+syswow64.py -- Crossing the heaven gate
+'''''''''''''''''''''''''''''''''''''''
+
+.. module:: windows.syswow64
+
+One of my goal with ``PythonForWindows`` is to have some abstraction of the bitness of the processes.
+It means being able to work on a ``32bits Python`` or a ``64bits Python``.
+
+In the case of a 32bits python on a ``64bits`` system (``SysWow64``) it's not trivial to perform operation on
+other ``64bits`` processes. For example directly calling :func:`CreateRemoteThread` will not work.
+
+To be able to perform those operation we must be able to execute code in the ``64bits`` part of our
+``SysWow64`` process.
+
+.. note::
+
+ See `Knockin’ on Heaven’s Gate – Dynamic Processor Mode Switching `_
+
+
+For that we need to jump to the 64bits segment of our process, execute some code then return.
+To do so, we need to use some ``far jump`` / ``far ret`` with the segments selector ``0x23`` (CS_32bits) and ``0x33`` (CS_64bits).
+
+The generation of this is quite ugly in my case.
+This code is in:
+
+.. function:: execute_64bits_code_from_syswow
+
+Once we are able to execute some code in the ``64bits`` part we need to create the code that will call our API (in NTDLL).
+To do that, I rely on the type information already present in the function of :mod:`windows.winproxy`.
+With these information we are able to know
+
+ * The name of the API
+ * The number of arguments
+
+Then I generate the correct x64 stub (using :mod:`windows.native_exec.simple_x64`) with the function:
+
+.. function:: generate_syswow64_call
+
+One problem I encountered is that our function must be able to pass values of 64bits, so passing arguments by register is not possible.
+
+For now I allocate a buffer where a python wrapper copy the parameters and the x64 stub retrieves them from here.
+
+(It might be possible to do something by creating a WINCFUNC with only ULONG64 parameters).
+
+.. function:: try_generate_stub_target
+
+The final result is a ``Python`` function like the one in :mod:`windows.winproxy`
+
+ * It copies the arguments in the buffer
+ * Jumps on the 32->64 stub
+ * X64 bits code retrieves the arguments in the buffer and setup the registers and the stack for the call
+ * Calls the API
+ * Returns to 32bits mode.
+
+.. class:: Syswow64ApiProxy
+
+Existing function are:
+
+.. function:: NtCreateThreadEx_32_to_64
+
+.. function:: NtQueryInformationProcess_32_to_64
+
+.. function:: NtQueryInformationThread_32_to_64
+
+.. function:: NtQueryVirtualMemory_32_to_64
+
+.. function:: NtGetContextThread_32_to_64
+
+.. function:: NtSetContextThread_32_to_64
+
+.. function:: LdrLoadDll_32_to_64
\ No newline at end of file
diff --git a/docs/source/native_exec.rst b/docs/source/native_exec.rst
new file mode 100644
index 0000000..f46e723
--- /dev/null
+++ b/docs/source/native_exec.rst
@@ -0,0 +1,236 @@
+.. module:: windows.native_exec
+
+``windows.native_exec`` -- Native Code Execution
+************************************************
+
+
+:mod:`windows.native_exec` allows to create `Python` functions calling native code.
+it also provides a simple assembler for x86 and x64.
+
+:mod:`windows.native_exec` provides those functions:
+
+.. autofunction:: windows.native_exec.create_function
+
+The :mod:`windows.native_exec` also contains some submodules:
+ * :mod:`windows.native_exec.cpuid`
+ * :mod:`windows.native_exec.simple_x86`
+ * :mod:`windows.native_exec.simple_x64`
+
+:mod:`windows.native_exec.cpuid` -- Interface to native CPUID
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+.. automodule:: windows.native_exec.cpuid
+ :no-show-inheritance:
+ :no-members: bitness
+
+Demo::
+
+ >>> import windows.native_exec.cpuid
+ >>> windows.native_exec.cpuid.do_cpuid(0)
+
+ >>> x = windows.native_exec.cpuid.do_cpuid(0)
+ >>> x.EAX
+ 13L
+ >>> x.EBX
+ 1970169159L
+ >>> windows.native_exec.cpuid.get_vendor_id()
+ 'GenuineIntel'
+ >>> windows.native_exec.cpuid.get_proc_family_model()
+ (6L, 58L)
+
+
+:mod:`windows.native_exec.simple_x86` -- X86 Assembler
+""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+.. module:: windows.native_exec.simple_x86
+
+The :mod:`windows.native_exec.simple_x86` module allows to create simple x86 code.
+
+Its features are:
+ * Forward - Backward jump (using labels)
+ * Non-string interface for conditional/context dependent generation
+
+
+.. note::
+ The assembler DOES NOT handle every instruction at all.
+
+
+The assembler instructions are `Python` object that may accept arguments representing
+the mnemonic operands.
+
+These parameters can be of type:
+ * :class:`str` (register)
+ * :class:`int` (int)
+ * :class:`mem_access` (memory access)
+
+.. autoclass:: windows.native_exec.simple_x86.mem_access
+ :members: prefix, base, index, scale, disp
+ :exclude-members: count
+
+The :class:`mem_access` object can be created:
+ * By hand
+ * Using :func:`create_displacement`
+ * Using :func:`mem`
+
+.. autofunction:: windows.native_exec.simple_x86.create_displacement
+.. autofunction:: windows.native_exec.simple_x86.deref
+.. autofunction:: windows.native_exec.simple_x86.mem
+
+Instruction assembling::
+
+ >>> import windows.native_exec.simple_x86 as x86
+ >>> import random
+ >>> x86.Mov
+
+ >>> instr = x86.Mov("EAX", "EBX")
+ >>> instr
+
+ >>> instr.get_code()
+ '\x89\xd8'
+ >>> x86.Mov("EAX", 0x42424242).get_code()
+ '\xc7\xc0BBBB'
+ >>> x86.Mov("EAX", x86.create_displacement(base="EAX", disp=random.randint(0, 0xffffffff))).get_code()
+ '\x8b\x80\x977\n&'
+ >>> x86.Mov(x86.mem("[EBX + EDI * 2 + 0x11111111]"), "EAX").get_code()
+ '\x89\x84{\x11\x11\x11\x11'
+ >>> x86.Mov(x86.mem("gs:[EBX + EDI * 2 + 0x11111111]"), "EAX").get_code()
+ 'e\x89\x84{\x11\x11\x11\x11'
+
+:mod:`windows.native_exec.simple_x86` also provides an interface to complex shellcode assembling
+including jump and label via the :class:`MultipleInstr` class.
+
+Shellcode assembling::
+
+ import windows.native_exec.simple_x86 as x86
+
+ code = x86.MultipleInstr()
+ code += x86.Label(":BEGIN")
+ code += x86.Jmp(":BEGIN")
+ print(repr(code.get_code()))
+ # '\xeb\xfe'
+
+Another example from a project::
+
+ IO_STACK_INPUT_BUFFER_LEN = x86.mem('[ESI + 8]')
+ IO_STACK_INPUT_BUFFER = x86.mem('[ESI + 0x10]')
+
+ INPUT_BUFFER_SIZE = x86.mem('[ECX]')
+ INPUT_BUFFER_PORT = x86.mem('[ECX + 4]')
+ INPUT_BUFFER_VALUE = x86.mem('[ECX + 8]')
+
+ out_ioctl = x86.MultipleInstr()
+ out_ioctl += x86.Cmp(IO_STACK_INPUT_BUFFER_LEN, 0xc) # size indicator / port / value
+ out_ioctl += x86.Jnz(":FAIL")
+ out_ioctl += x86.Mov('ECX', IO_STACK_INPUT_BUFFER)
+ out_ioctl += x86.Mov('EDX', INPUT_BUFFER_PORT)
+ out_ioctl += x86.Mov('EAX', INPUT_BUFFER_VALUE)
+ out_ioctl += x86.Mov('ECX', INPUT_BUFFER_SIZE)
+ out_ioctl += x86.Cmp('ECX', 0x1)
+ out_ioctl += x86.Jnz(":OUT_2_OR_4")
+ out_ioctl += x86.Out('DX', 'AL')
+ out_ioctl += x86.Jmp(':SUCCESS')
+ out_ioctl += x86.Label(":OUT_2_OR_4")
+ out_ioctl += x86.Cmp('ECX', 0x2)
+ out_ioctl += x86.Jnz(":OUT_4")
+ out_ioctl += x86.Out('DX', 'AX')
+ out_ioctl += x86.Jmp(':SUCCESS')
+ out_ioctl += x86.Label(":OUT_4")
+ out_ioctl += x86.Out('DX', 'EAX')
+ out_ioctl += x86.Label(":SUCCESS")
+ out_ioctl += x86.Xor('EAX', 'EAX')
+ out_ioctl += x86.Ret()
+ out_ioctl += x86.Label(":FAIL")
+ out_ioctl += x86.Mov('EAX', 0x0C000000D)
+ out_ioctl += x86.Ret()
+
+ out_ioctl.get_code()
+ '\x81~\x08\x0c\x00\x00\x00u&\x8bN\x10\x8bQ\x04\x8bA\x08\x8b\t\x81\xf9\x01\x00\x00\x00u\x03\xee\xeb\r\x81\xf9\x02\x00\x00\x00u\x04f\xef\xeb\x01\xef1\xc0\xc3\xc7\xc0\r\x00\x00\xc0\xc3'
+
+
+:mod:`windows.native_exec.simple_x64` -- X64 Assembler
+""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+.. module:: windows.native_exec.simple_x64
+
+Same things as :mod:`windows.native_exec.simple_x86`
+
+The only things that change are:
+ * The registers name
+
+:mod:`windows.native_exec.simple_x64` handles 32 and 64 bits operations.
+
+Demo::
+
+ >>> import windows.native_exec.simple_x64 as x64
+ >>> x64.Mov("RAX", "R13").get_code()
+ 'L\x89\xe8'
+ >>> x64.Mov("EAX", "EDI").get_code()
+ '\x89\xf8'
+ >>> x64.Mov("RAX", "EDI").get_code()
+ """
+ ValueError: Size mismatch
+ """
+ >>> x64.Mov("RAX", x64.mem("[EAX]")).get_code()
+ 'gH\x8b\x00'
+ >>> x64.Mov("RAX", x64.mem("[RAX]")).get_code()
+ 'H\x8b\x00'
+ >>> x64.Mov("EAX", x64.mem("[RAX]")).get_code()
+ '\x8b\x00'
+ >>> x64.Mov("EAX", x64.mem("[EAX]")).get_code()
+ 'g\x8b\x00'
+
+
+
+:mod:`windows.native_exec.nativeutils` -- Native utility functions
+""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+.. module:: windows.native_exec.nativeutils
+
+This module contains some native-code functions that can be used for various purposes.
+Each function export a label that allow another :class:`MultipleInstr` to call the code of the function.
+
+The current functions are:
+
+ * ``StrlenW64`` A 64bits wide-string STRLEN (``Label(":FUNC_STRLENW64")``)
+ * ``StrlenA64`` A 64bits ASCII STRLEN (``Label(":FUNC_STRLENA64")``)
+ * ``GetProcAddress64`` A 64bits export resolver (``Label(":FUNC_GETPROCADDRESS64")``)
+
+ * Arg1: The DLL (wstring)
+ * Arg2: The API (string)
+ * Return value:
+
+ * 0xfffffffffffffffe if the DLL is not found
+ * 0xffffffffffffffff if the API is not found
+ * The address of the function
+
+ * ``StrlenW32`` A 32bits wide-string STRLEN (``Label(":FUNC_STRLENW32")``)
+ * ``StrlenA32`` A 32bits ASCII STRLEN (``Label(":FUNC_STRLENA32")``)
+ * ``GetProcAddress32`` A 32bits export resolver (``Label(":FUNC_GETPROCADDRESS32")``)
+
+ * Arg1: The DLL (wstring)
+ * Arg2: The API (string)
+ * Return value:
+
+ * 0xfffffffe if the DLL is not found
+ * 0xffffffff if the API is not found
+ * The address of the function
+
+To use those functions in a :class:`MultipleInstr` just call the label in your code and append the function at
+the end of your :class:`MultipleInstr`
+
+
+Example::
+
+ RemoteManualLoadLibray = x86.MultipleInstr()
+
+ RemoteManualLoadLibray += x86.Mov("ECX", x86.mem("[ESP + 4]"))
+ RemoteManualLoadLibray += x86.Push(x86.mem("[ECX + 4]"))
+ RemoteManualLoadLibray += x86.Push(x86.mem("[ECX]"))
+ RemoteManualLoadLibray += x86.Call(":FUNC_GETPROCADDRESS32")
+ RemoteManualLoadLibray += x86.Push(x86.mem("[ECX + 8]"))
+ RemoteManualLoadLibray += x86.Call("EAX") # LoadLibrary
+ RemoteManualLoadLibray += x86.Pop("ECX")
+ RemoteManualLoadLibray += x86.Pop("ECX")
+ RemoteManualLoadLibray += x86.Ret()
+
+ RemoteManualLoadLibray += GetProcAddress32
\ No newline at end of file
diff --git a/docs/source/network.rst b/docs/source/network.rst
new file mode 100644
index 0000000..2e64fd3
--- /dev/null
+++ b/docs/source/network.rst
@@ -0,0 +1,27 @@
+Network
+=======
+
+.. module:: windows.winobject.network
+
+.. note::
+
+ See sample :ref:`sample_network_exploration`
+
+
+.. autoclass:: Network
+
+Connections
+"""""""""""
+
+.. autoclass:: TCP4Connection
+
+
+.. autoclass:: TCP6Connection
+
+Firewall
+""""""""
+
+.. autoclass:: Firewall
+
+
+.. autoclass:: FirewallRule
\ No newline at end of file
diff --git a/docs/source/process.rst b/docs/source/process.rst
new file mode 100644
index 0000000..fd0f77b
--- /dev/null
+++ b/docs/source/process.rst
@@ -0,0 +1,128 @@
+Processes and Threads
+"""""""""""""""""""""
+
+.. module:: windows.winobject.process
+
+CurrentProcess
+''''''''''''''
+
+.. note::
+
+ See sample :ref:`sample_current_process`
+
+.. autoclass:: CurrentProcess
+ :members:
+ :show-inheritance:
+ :inherited-members:
+
+CurrentThread
+'''''''''''''
+
+.. autoclass:: CurrentThread
+ :members:
+ :show-inheritance:
+ :inherited-members:
+
+WinProcess
+''''''''''
+
+.. note::
+
+ See sample :ref:`sample_remote_process`
+
+.. autoclass:: WinProcess
+ :members:
+ :show-inheritance:
+ :inherited-members:
+
+
+WinThread
+'''''''''
+
+.. autoclass:: WinThread
+ :members:
+ :show-inheritance:
+ :inherited-members:
+
+
+.. autoclass:: DeadThread
+ :members:
+ :show-inheritance:
+ :inherited-members:
+
+Token
+'''''
+
+.. autoclass:: Token
+ :members:
+ :inherited-members:
+
+
+PEB Exploration
+"""""""""""""""
+
+The :mod:`windows` module is able to parse the PEB of the current process or remote process.
+The :class:`PEB` is accessible via ``process.peb`` and is of type :class:`PEB`.
+
+.. note::
+
+ See sample :ref:`sample_peb_exploration`
+
+PEB
+'''
+
+.. autoclass:: PEB
+ :members:
+ :inherited-members:
+
+.. autoclass:: WinUnicodeString
+
+LoadedModule
+''''''''''''
+
+.. autoclass:: LoadedModule
+
+
+PEFile - Parsing loaded PE
+""""""""""""""""""""""""""
+
+:mod:`windows.pe_parse`
+'''''''''''''''''''''''
+
+.. module:: windows.pe_parse
+
+.. autofunction:: windows.pe_parse.GetPEFile
+
+PEFile
+^^^^^^
+
+.. autoclass:: PEFile
+
+IATEntry
+^^^^^^^^
+
+.. autoclass:: IATEntry
+
+ .. data:: addr
+
+ :class:`int` : Address of the IAT Entry
+
+ .. data:: ord
+
+ :class:`int` : Ordinal of the imported function
+
+ .. data:: name
+
+ :class:`int` : Name of the imported function
+
+ .. data:: value
+
+ :class:`int` : The content (destination) of the IAT entry
+
+ .. warning::
+
+ `value` is a descriptor. Setting its value will actually CHANGE THE IAT ENTRY, resulting in a segfault if no VirtualProtect have been done.
+
+ .. note::
+
+ See: :class:`windows.utils.VirtualProtected`
\ No newline at end of file
diff --git a/docs/source/registry.rst b/docs/source/registry.rst
new file mode 100644
index 0000000..cf1f0ba
--- /dev/null
+++ b/docs/source/registry.rst
@@ -0,0 +1,38 @@
+Registry
+========
+
+.. module:: windows.winobject.registry
+
+.. note::
+
+ See sample :ref:`sample_registry`
+
+Registry
+""""""""
+
+.. autoclass:: Registry
+ :special-members: __getitem__
+
+
+PyHKey
+""""""
+
+.. autoclass:: PyHKey
+
+ .. function:: __call__(name)
+
+ Alias for :func:`open_subkey`
+
+ .. function:: __getitem__(name)
+
+ Alias for :func:`get`
+
+ .. function:: __setitem__(name)
+
+ Wrapper for :func:`set`, accept ``value`` or ``(value, type)``
+
+KeyValue
+""""""""
+
+.. autoclass:: KeyValue
+ :exclude-members: count, index
\ No newline at end of file
diff --git a/docs/source/sample.rst b/docs/source/sample.rst
new file mode 100644
index 0000000..eb683da
--- /dev/null
+++ b/docs/source/sample.rst
@@ -0,0 +1,508 @@
+Samples of code
+===============
+
+.. _sample_current_process:
+
+``windows.current_process``
+"""""""""""""""""""""""""""
+
+.. literalinclude:: ..\..\samples\current_process.py
+
+Output::
+
+ (cmd λ) python32.exe current_process.py
+ current process is
+ current process is a <32> bits process
+ current process is a SysWow64 process ?
+ current process pid <8264> and ppid <4100>
+ Here are the current process threads: <[]>
+ Let's execute some native code ! (0x41 + 1)
+ Native code returned <0x42>
+ Allocating memory in current process
+ Allocated memory is at <0xd60000>
+ Writing 'SOME STUFF' in allocation memory
+ Reading memory : <'SOME STUFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'>
+
+.. _sample_remote_process:
+
+Remote process : :class:`WinProcess`
+""""""""""""""""""""""""""""""""""""
+
+.. literalinclude:: ..\..\samples\remote_calc.py
+
+Output::
+
+ (cmd λ) python.exe remote_calc.py
+ Creating a calc
+ Looking for calcs in the processes
+ They are currently <1> calcs running on the system
+ Let's play with our calc: <>
+ Our calc pid is 8052
+ Our calc is a <32> bits process
+ Our calc is a SysWow64 process ?
+ Our calc have threads ! <[, , ]>
+ Exploring our calc PEB !
+ Command line is
+ Here are 3 loaded modules: [, , ]
+ Allocating memory in our calc
+ Allocated memory is at <0x5c90000>
+ Writing 'SOME STUFF' in allocated memory
+ Reading allocated memory : <'SOME STUFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'>
+ Execution some native code in our calc (write 0x424242 at allocated address + return 0x1337
+ Executing native code !
+ Return code = 0x1337L
+ Reading allocated memory : <'BBBB STUFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'>
+ Executing python code !
+ Reading allocated memory : <'HELLO FROM CALC\x00\x00\x00\x00\x00'>
+ Trying to import in remote module 'FAKE_MODULE'
+ Remote ERROR !
+ Traceback (most recent call last):
+ File "", line 3, in
+ File "", line 2, in func
+ ImportError: No module named FAKE_MODULE
+
+ That's all ! killing the calc
+
+
+.. _sample_peb_exploration:
+
+:class:`PEB` exploration
+""""""""""""""""""""""""
+
+.. literalinclude:: ..\..\samples\peb.py
+
+Output::
+
+ (cmd λ) python.exe peb.py
+ Exploring the current process PEB
+ PEB is <>
+ Commandline object is
+ Commandline string is u'python.exe peb.py '
+ Imagepath
+ Printing some modules:
+
+
+
+
+
+ === K32 ===
+ Looking for kernel32.dll
+ Kernel32 module:
+ Module name = | Fullname =
+ Kernel32 is loaded at address 0x774c0000
+ === K32 PE ===
+ PE Representation of k32:
+ Here are some exports {0: 2001566688L, u'CreateFileA': 2001635616L, 42: 2001647872L, u'VirtualAlloc': 2001570704L}
+ Import DLL dependancies are (without api-*): [u'ntdll.dll', u'kernelbase.dll']
+ IAT Entry for ntdll!NtCreateFile = | addr = 0x77541128L
+ Sections: [, , , , ]
+
+
+
+.. _sample_system:
+
+
+``windows.system``
+""""""""""""""""""
+
+.. literalinclude:: ..\..\samples\system.py
+
+Output::
+
+ (cmd λ) python system.py
+ Basic system infos:
+ version = (6, 3)
+ bitness = 64
+ computer_name = HAKRIL-PC
+ product_type = VER_NT_WORKSTATION(0x1L)
+ version_name = Windows 8.1
+
+ There is 117 processes
+ There is 1246 threads
+
+ Dumping first logical drive:
+
+ name = C:\
+ type = DRIVE_FIXED(0x3L)
+ path = \Device\HarddiskVolume2
+
+ Dumping first service:
+
+ name = ACPI
+ description = Microsoft ACPI Driver
+ status = ServiceStatus(type=SERVICE_KERNEL_DRIVER(0x1L), state=SERVICE_RUNNING(0x4L), control_accepted=1L, flags=0L)
+ process = None
+
+ Finding a service in a user process:
+
+ name = Appinfo
+ description = Application Information
+ status = ServiceStatus(type=SERVICE_WIN32_SHARE_PROCESS(0x20L), state=SERVICE_RUNNING(0x4L), control_accepted=129L, flags=0L)
+ process =
+
+ Enumerating handles:
+ There are 40664 handles:
+ First handle is: in process pid=4>
+ Enumerating handles of the current process:
+ There are 255 handles for this process
+ Looking for a File handle:
+ Handle is in process pid=14340>
+ Name is <\Device\ConDrv>
+
+.. _sample_iat_hook:
+
+IAT hooking
+"""""""""""
+
+.. literalinclude:: ..\..\samples\iat_hook.py
+
+Output::
+
+ (cmd λ) python iat_hook.py
+ Asking for
+ Hook called | hKey = 0x12d687 | lpSubKey =
+ Secret key asked, returning magic handle 0x12345678
+ Result = 0x12345678
+
+ Asking for
+ Hook called | hKey = 0x12d687 | lpSubKey =
+ Asked for a failing key: returning 0x2a
+ WindowsError(42, 'Windows Error 0x2A')
+
+ Asking for
+ Hook called | hKey = 0x80000001L | lpSubKey =
+ Non-secret key : calling normal function
+ Result = 0x108
+
+.. _sample_network_exploration:
+
+:class:`Network` - socket exploration
+"""""""""""""""""""""""""""""""""""""
+
+.. literalinclude:: ..\..\samples\network.py
+
+Output::
+
+ (cmd λ) python.exe network.py
+ Working on ipv4
+ == Listening ==
+ Some listening connections: [, , ]
+ Listening ports are : [80, 135, 443, 445, 902, 912, 5357, 49152, 49153, 49154, 49155, 49157, 49159, 8307, 25340, 139, 139]
+ == Established ==
+ Some established connections: [ 127.0.0.1:49472>, 127.0.0.1:49174>, 127.0.0.1:49173>]
+ == connection to localhost:80 ==
+ Our connection is [ 127.0.0.1:80>]
+ Sending YOP
+ Closing socket
+ Sending LAIT
+ Traceback (most recent call last):
+ File ".\network.py", line 45, in
+ s.send("LAIT")
+ socket.error: [Errno 10054] An existing connection was forcibly closed by the remote host
+
+
+.. _sample_registry:
+
+:class:`Registry`
+"""""""""""""""""
+
+.. literalinclude:: ..\..\samples\registry.py
+
+Output::
+
+ (cmd λ) python.exe registry.py
+ Registry is <>
+ HKEY_CURRENT_USER is <>
+ HKEY_CURRENT_USER subkeys names are:
+ ['AppEvents',
+ 'AppXBackupContentType',
+ 'Console',
+ 'Control Panel',
+ 'Environment',
+ 'EUDC',
+ 'Identities',
+ 'Keyboard Layout',
+ 'Network',
+ 'Printers',
+ 'Software',
+ 'System',
+ 'Volatile Environment']
+ Opening 'Software' in HKEY_CURRENT_USER:
+ We can also open it in one access:
+ Looking at CurrentVersion
+ Key is
+ values are:
+ [KeyValue(name='SoftwareType', value=u'System', type=1),
+ KeyValue(name='RegisteredOwner', value=u'hakril', type=1),
+ KeyValue(name='InstallDate', value=0, type=4),
+ ...
+ KeyValue(name='PathName', value=u'C:\\Windows', type=1)]
+ registered owner =
+
+
+.. _sample_wintrust:
+
+``windows.wintrust``
+""""""""""""""""""""
+
+.. literalinclude:: ..\..\samples\wintrust.py
+
+Output::
+
+ (cmd λ) python .\wintrust.py
+ Checking signature of
+ is_signed:
+ check_signature: <0>
+ full_signature_information:
+ * signed
+ * catalog
+ * catalogsigned
+ * additionalinfo <0>
+ Checking signature of some loaded DLL
+ : False (TRUST_E_NOSIGNATURE(0x800b0100L))
+ : True
+ : True
+ : True
+ : False (TRUST_E_NOSIGNATURE(0x800b0100L))
+
+.. _sample_vectoredexception:
+
+:func:`VectoredException`
+"""""""""""""""""""""""""
+
+In local process
+''''''''''''''''
+
+.. literalinclude:: ..\..\samples\veh_segv.py
+
+Output::
+
+ (cmd λ) python.exe veh_segv.py
+ Protected page is at <0x1db0000>
+ Setting page protection to
+
+ ==Entry of VEH handler==
+ Instr at 0x1d1ab574 accessed to addr 0x1db0000
+ Resetting page protection to
+ ==Entry of VEH handler==
+ Exception of type EXCEPTION_SINGLE_STEP(0x80000004L)
+ Resetting page protection to
+ Value 1 read
+
+ ==Entry of VEH handler==
+ Instr at 0x1d1ab574 accessed to addr 0x1db0010
+ Resetting page protection to
+ ==Entry of VEH handler==
+ Exception of type EXCEPTION_SINGLE_STEP(0x80000004L)
+ Resetting page protection to
+ Value 2 read
+
+
+In remote process
+'''''''''''''''''
+
+.. literalinclude:: ..\..\samples\remote_veh_segv.py
+
+Output::
+
+ (cmd λ) python .exe.\samples\remote_veh_segv.py
+ (In another console)
+
+ Tracing execution in module:
+ Protected page is at 0x7ffa3c700000L
+
+ Instr at 0x7ffa3c70f0f0L accessed to addr 0x7ffa3c70f0f0L (gdi32.dll)
+ Exception of type EXCEPTION_SINGLE_STEP(0x80000004L)
+ Resetting page protection to
+
+ Instr at 0x7ffa3c70f0f5L accessed to addr 0x7ffa3c70f0f5L (gdi32.dll)
+ Exception of type EXCEPTION_SINGLE_STEP(0x80000004L)
+ Resetting page protection to
+
+ Instr at 0x7ffa3c70f0faL accessed to addr 0x7ffa3c70f0faL (gdi32.dll)
+ Exception of type EXCEPTION_SINGLE_STEP(0x80000004L)
+ Resetting page protection to
+
+ Instr at 0x7ffa3c70f0ffL accessed to addr 0x7ffa3c70f0ffL (gdi32.dll)
+ Exception of type EXCEPTION_SINGLE_STEP(0x80000004L)
+ Resetting page protection to
+
+ Instr at 0x7ffa3c70f100L accessed to addr 0x7ffa3c70f100L (gdi32.dll)
+ No more tracing !
+
+
+.. _sample_debugger:
+
+Debugging
+"""""""""
+
+:class:`Debugger`
+'''''''''''''''''
+
+.. literalinclude:: ..\..\samples\debugger_print_LdrLoaddll.py
+
+Ouput::
+
+ (cmd λ) python.exe .\samples\debugger_print_LdrLoaddll.py
+ Loading
+ Got exception EXCEPTION_BREAKPOINT(0x80000003L) at 0x77a73bad
+ Loading
+ Loading
+ Loading
+ Loading
+ Loading
+ Loading
+ Loading
+ Loading
+ Loading
+ Loading
+ Loading
+ Loading
+ Loading
+ Ask to load : exiting process
+
+
+Single stepping
+~~~~~~~~~~~~~~~
+
+.. literalinclude:: ..\..\samples\debugger_membp_singlestep.py
+
+Ouput::
+
+ (cmd λ) python.exe .\samples\debugger_membp_singlestep.py
+ Got exception EXCEPTION_BREAKPOINT(0x80000003L) at 0x77ae3c7d
+ Instruction at <0x8d0006> wrote at <0x8e0000>
+ Got single_step EXCEPTION_SINGLE_STEP(0x80000004L) at 0x8d000c
+ Got single_step EXCEPTION_SINGLE_STEP(0x80000004L) at 0x8d0011
+ Instruction at <0x8d0011> wrote at <0x8e0004>
+ Got single_step EXCEPTION_SINGLE_STEP(0x80000004L) at 0x8d0017
+ Got single_step EXCEPTION_SINGLE_STEP(0x80000004L) at 0x8d001c
+ Got single_step EXCEPTION_SINGLE_STEP(0x80000004L) at 0x8d0022
+ Got single_step EXCEPTION_SINGLE_STEP(0x80000004L) at 0x8d0023
+ No more single step: exiting
+
+
+:class:`windows.debug.FunctionBP`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. literalinclude:: ..\..\samples\debug_functionbp.py
+
+Ouput::
+
+ NtCreateFile of <\??\C:\Windows\syswow64\en-US\calc.exe.mui>: handle = 0xac
+ Handle manually found! typename=, name=<\Device\HarddiskVolume2\Windows\SysWOW64\en-US\calc.exe.mui>
+
+ NtCreateFile of <\Device\DeviceApi\CMApi>: handle = 0x108
+ Handle manually found! typename=, name=<\Device\DeviceApi>
+
+ NtCreateFile of <\??\C:\Windows\Fonts\staticcache.dat>: handle = 0x154
+ Handle manually found! typename=, name=<\Device\HarddiskVolume2\Windows\Fonts\StaticCache.dat>
+
+ Exiting process
+
+.. _sample_local_debugger:
+
+
+:class:`LocalDebugger`
+''''''''''''''''''''''
+
+In current process
+^^^^^^^^^^^^^^^^^^
+
+.. literalinclude:: ..\..\samples\local_debugger.py
+
+Ouput::
+
+ (cmd λ) python.exe .\samples\local_debugger.py
+ Code addr = 0xcf0002
+ GOT AN HXBP at 0xcf0002
+ EXCEPTION !!!! Got a EXCEPTION_SINGLE_STEP(0x80000004L) at 0xcf0003
+ EXCEPTION !!!! Got a EXCEPTION_SINGLE_STEP(0x80000004L) at 0xcf0004
+ EXCEPTION !!!! Got a EXCEPTION_SINGLE_STEP(0x80000004L) at 0xcf0005
+ EXCEPTION !!!! Got a EXCEPTION_SINGLE_STEP(0x80000004L) at 0x770d7c04
+ Done!
+
+
+In remote process
+^^^^^^^^^^^^^^^^^
+
+.. literalinclude:: ..\..\samples\local_debugger_remote_process.py
+
+Ouput::
+
+ (cmd λ) python.exe .\samples\local_debugger_remote_process.py
+ (In another console)
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+ I AM LOADING
+
+
+.. _wmi_request:
+
+Make WMI requests
+'''''''''''''''''
+
+.. literalinclude:: ..\..\samples\wmi_request.py
+
+
+Ouput::
+
+ (cmd λ) python .\samples\wmi_request.py
+ WMI requester is
+ Selecting * from 'Win32_Process'
+ They are <92> processes
+ Looking for ourself via pid
+ Some info about our process:
+ * Name -> python.exe
+ * ProcessId -> 7968
+ * OSName -> Microsoft Windows 8.1 Pro|C:\Windows|\Device\Harddisk0\Partition2
+ * UserModeTime -> 2812500
+ * WindowsVersion -> 6.3.9600
+ * CommandLine -> python.exe .\samples\wmi_request.py
+ :
+ * {'Caption': u'C:', 'FreeSpace': u'43991547904', 'FileSystem': u'NTFS'}
+ * {'Caption': u'E:', 'FreeSpace': u'82776027136', 'FileSystem': u'NTFS'}
+ * {'Caption': u'F:', 'FreeSpace': u'5711265792', 'FileSystem': u'FAT32'}
+ * {'Caption': u'G:', 'FreeSpace': None, 'FileSystem': None}
+
+.. _sample_com_firewall:
+
+using COM: ``INetFwPolicy2``
+''''''''''''''''''''''''''''
+
+.. literalinclude:: ..\..\samples\com_inetfwpolicy2.py
+
+Output::
+
+ (cmd λ) python .\samples\com_inetfwpolicy2.py
+ Initialisation of COM
+ Creating INetFwPolicy2 variable
+ (value = None)
+
+ Generating CLSID
+
+
+ Creating COM instance
+ (value = 0x8984848)
+
+ Checking for enabled profiles
+ * NET_FW_PROFILE2_DOMAIN(0x1L) -> True
+ * NET_FW_PROFILE2_PRIVATE(0x2L) -> True
+ * NET_FW_PROFILE2_PUBLIC(0x4L) -> True
\ No newline at end of file
diff --git a/docs/source/service.rst b/docs/source/service.rst
new file mode 100644
index 0000000..6c1d041
--- /dev/null
+++ b/docs/source/service.rst
@@ -0,0 +1,15 @@
+Service
+=======
+
+.. note::
+
+ See sample :ref:`sample_system`
+
+.. module:: windows.winobject.service
+
+.. autoclass:: ServiceStatus
+ :exclude-members: count, index
+
+.. autoclass:: ServiceA
+ :show-inheritance:
+ :inherited-members:
\ No newline at end of file
diff --git a/docs/source/utils.rst b/docs/source/utils.rst
new file mode 100644
index 0000000..c4b7806
--- /dev/null
+++ b/docs/source/utils.rst
@@ -0,0 +1,34 @@
+``windows.utils`` -- Windows Utilities
+***********************************************
+
+.. module:: windows.utils
+
+Context Managers
+""""""""""""""""
+
+:mod:`windows.utils` provides some context managers wrapping `standard` contextual operations
+like ``VirtualProtect`` or ``SysWow Redirection``
+
+VirtualProtected
+''''''''''''''''
+
+.. autoclass:: windows.utils.VirtualProtected
+ :no-show-inheritance:
+
+DisableWow64FsRedirection
+'''''''''''''''''''''''''
+
+.. autoclass:: windows.utils.DisableWow64FsRedirection
+ :no-show-inheritance:
+
+Helper functions
+""""""""""""""""
+
+.. autofunction:: windows.utils.enable_privilege
+.. autofunction:: windows.utils.check_is_elevated
+.. autofunction:: windows.utils.check_debug
+.. autofunction:: windows.utils.create_process
+.. autofunction:: windows.utils.create_console
+.. autofunction:: windows.utils.pop_shell
+.. autofunction:: windows.utils.create_file_from_handle
+.. autofunction:: windows.utils.get_handle_from_file
\ No newline at end of file
diff --git a/docs/source/various.rst b/docs/source/various.rst
new file mode 100644
index 0000000..f0c2e60
--- /dev/null
+++ b/docs/source/various.rst
@@ -0,0 +1,19 @@
+The :mod:`windows` objects
+==========================
+
+Through the :ref:`system ` object many classes representing various `Windows`
+parts are accessible.
+
+This sections describes them by group of relation.
+
+.. toctree::
+ :maxdepth: 3
+
+ process.rst
+ exception.rst
+ registry.rst
+ network.rst
+ service.rst
+ volume.rst
+ wmi.rst
+ handle.rst
\ No newline at end of file
diff --git a/docs/source/volume.rst b/docs/source/volume.rst
new file mode 100644
index 0000000..60d440d
--- /dev/null
+++ b/docs/source/volume.rst
@@ -0,0 +1,16 @@
+Volume -- The logical drives
+============================
+
+.. note::
+
+ See sample :ref:`sample_system`
+
+.. module:: windows.winobject.volume
+
+.. autoclass:: LogicalDrive
+
+ .. data:: name
+
+ Name of the logical drive
+
+ :type: :class:`str`
\ No newline at end of file
diff --git a/docs/source/windows.rst b/docs/source/windows.rst
new file mode 100644
index 0000000..d0b658b
--- /dev/null
+++ b/docs/source/windows.rst
@@ -0,0 +1,34 @@
+The ``windows`` module
+**********************
+
+The ``windows`` module is the module installed by :file:`setup.py`.
+
+This module exports some objects representing the current state of the system.
+It also offers some submodules aimed to help the interfacing with ``Windows`` and native code execution.
+
+The defaults objects accessible in ``windows`` are:
+ * ``system`` of type :class:`windows.winobject.system.System`
+ * ``current_process`` of type :class:`windows.winobject.process.CurrentProcess`
+ * ``current_thread`` of type :class:`windows.winobject.process.CurrentThread`
+
+The submodules that you might use by themself are:
+ * :mod:`windows.native_exec`
+ * :mod:`windows.winproxy`
+ * :mod:`windows.utils`
+ * :mod:`windows.debug`
+ * :mod:`windows.com`
+
+.. _object_system:
+
+The ``system`` object
+"""""""""""""""""""""
+
+.. note::
+
+ See sample :ref:`sample_system`
+
+.. currentmodule:: windows.winobject
+
+.. autoclass:: windows.winobject.system.System
+ :no-show-inheritance:
+
diff --git a/docs/source/winproxy.rst b/docs/source/winproxy.rst
new file mode 100644
index 0000000..f437b61
--- /dev/null
+++ b/docs/source/winproxy.rst
@@ -0,0 +1,830 @@
+``windows.winproxy`` -- Windows API
+***********************************
+
+.. module:: windows.winproxy
+
+:mod:`windows.winproxy` tries to be a pythontic wrapper around windows API of various DLL.
+It also heavily relies on :mod:`ctypes` and :mod:`windows.generated_def.winfuncs`
+
+Here are the things to know about :mod:`windows.winproxy`
+ * All of this is based on :mod:`windows.generated_def.winfuncs`
+ * DLL is loaded the first time an API of it is called
+ * All parameters can be passed by ordinal or keyword
+ * The call will fail if an argument with default value ``NeededParamater`` have been called without another value.
+ * The call will raise a subclass of :class:`WindowsError` if it fails.
+ * Some functions are 'transparent proxy' it means that all parameters are mandatory
+
+Example: ``VirtualAlloc``
+"""""""""""""""""""""""""
+
+Exemple with the function `VirtualAlloc` in :mod:`windows.winproxy`
+
+Documentation:
+
+.. code-block:: python
+
+ import windows
+ windows.winproxy.VirtualAlloc
+ #
+
+ help(windows.winproxy.VirtualAlloc)
+ # Help on function VirtualAlloc in module windows.winproxy:
+ # VirtualAlloc(lpAddress=0, dwSize=NeededParameter, flAllocationType=MEM_COMMIT(0x1000L), flProtect=PAGE_EXECUTE_READWRITE(0x40L))
+ # Errcheck:
+ # raise Kernel32Error if result is 0
+
+
+Calling it
+
+.. code-block:: python
+
+ import windows
+
+ # Ordinal arguments
+ windows.winproxy.VirtualAlloc(0, 0x1000)
+ 34537472
+
+ # Keyword arguments
+ windows.winproxy.VirtualAlloc(dwSize=0x1000)
+ 34603008
+
+ # NeededParameter must be provided
+ windows.winproxy.VirtualAlloc()
+ """
+ Traceback (most recent call last):
+ File "", line 1, in
+ File "windows\winproxy.py", line 264, in VirtualAlloc
+ return VirtualAlloc.ctypes_function(lpAddress, dwSize, flAllocationType, flProtect)
+ File "windows\winproxy.py", line 130, in perform_call
+ raise TypeError("{0}: Missing Mandatory parameter <{1}>".format(self.func_name, param_name))
+ TypeError: VirtualAlloc: Missing Mandatory parameter
+ """
+
+ # Error raises exception
+ windows.winproxy.VirtualAlloc(dwSize=0xffffffff)
+ """
+ Traceback (most recent call last):
+ File "", line 1, in
+ File "windows\winproxy.py", line 264, in VirtualAlloc
+ return VirtualAlloc.ctypes_function(lpAddress, dwSize, flAllocationType, flProtect)
+ File "windows\winproxy.py", line 133, in perform_call
+ return self._cprototyped(*args)
+ File "windows\winproxy.py", line 59, in kernel32_error_check
+ raise Kernel32Error(func_name)
+ windows.winproxy.Kernel32Error: VirtualAlloc: [Error 8] Not enough storage is available to process this command.
+ """
+
+
+Functions in :mod:`windows.winproxy`
+""""""""""""""""""""""""""""""""""""
+
+Transparent proxies:
+
+* AllocConsole()
+* CloseHandle(hObject)
+* ContinueDebugEvent(dwProcessId, dwThreadId, dwContinueStatus)
+* DebugActiveProcess(dwProcessId)
+* DebugActiveProcessStop(dwProcessId)
+* DebugBreak()
+* DebugBreakProcess(Process)
+* DebugSetProcessKillOnExit(KillOnExit)
+* EnumWindows(lpEnumFunc, lParam)
+* ExitProcess(uExitCode)
+* ExitThread(dwExitCode)
+* FreeConsole()
+* GetComputerNameA(lpBuffer, lpnSize)
+* GetComputerNameW(lpBuffer, lpnSize)
+* GetCurrentProcess()
+* GetCurrentProcessorNumber()
+* GetCurrentThread()
+* GetCurrentThreadId()
+* GetDriveTypeA(lpRootPathName)
+* GetDriveTypeW(lpRootPathName)
+* GetExitCodeProcess(hProcess, lpExitCode)
+* GetExitCodeThread(hThread, lpExitCode)
+* GetLastError()
+* GetLogicalDriveStringsA(nBufferLength, lpBuffer)
+* GetLogicalDriveStringsW(nBufferLength, lpBuffer)
+* GetProcAddress(hModule, lpProcName)
+* GetProcessId(Process)
+* GetSidSubAuthority(pSid, nSubAuthority)
+* GetSidSubAuthorityCount(pSid)
+* GetStdHandle(nStdHandle)
+* GetSystemMetrics(nIndex)
+* GetThreadId(Thread)
+* GetVersionExA(lpVersionInformation)
+* GetVersionExW(lpVersionInformation)
+* GetVolumeNameForVolumeMountPointA(lpszVolumeMountPoint, lpszVolumeName, cchBufferLength)
+* GetVolumeNameForVolumeMountPointW(lpszVolumeMountPoint, lpszVolumeName, cchBufferLength)
+* GetWindowModuleFileNameA(hwnd, pszFileName, cchFileNameMax)
+* GetWindowModuleFileNameW(hwnd, pszFileName, cchFileNameMax)
+* GetWindowTextA(hWnd, lpString, nMaxCount)
+* GetWindowTextW(hWnd, lpString, nMaxCount)
+* LoadLibraryA(lpFileName)
+* LoadLibraryW(lpFileName)
+* QueryDosDeviceA(lpDeviceName, lpTargetPath, ucchMax)
+* QueryDosDeviceW(lpDeviceName, lpTargetPath, ucchMax)
+* ResumeThread(hThread)
+* SetStdHandle(nStdHandle, hHandle)
+* SetTcpEntry(pTcpRow)
+* SuspendThread(hThread)
+* TerminateProcess(hProcess, uExitCode)
+* TerminateThread(hThread, dwExitCode)
+* VirtualQueryEx(hProcess, lpAddress, lpBuffer, dwLength)
+* Wow64DisableWow64FsRedirection(OldValue)
+* Wow64EnableWow64FsRedirection(Wow64FsEnableRedirection)
+* Wow64GetThreadContext(hThread, lpContext)
+* Wow64RevertWow64FsRedirection(OldValue)
+* lstrcmpA(lpString1, lpString2)
+* lstrcmpW(lpString1, lpString2)
+
+Functions:
+
+* AddVectoredContinueHandler::
+
+ AddVectoredContinueHandler(FirstHandler=1, VectoredHandler=NeededParameter)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* AddVectoredExceptionHandler::
+
+ AddVectoredExceptionHandler(FirstHandler=1, VectoredHandler=NeededParameter)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* AdjustTokenPrivileges::
+
+ AdjustTokenPrivileges(TokenHandle, DisableAllPrivileges=False, NewState=NeededParameter, BufferLength=None, PreviousState=None, ReturnLength=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* AlpcGetMessageAttribute::
+
+ AlpcGetMessageAttribute(Buffer, AttributeFlag)
+ Errcheck:
+ Nothing special
+
+* AlpcInitializeMessageAttribute::
+
+ AlpcInitializeMessageAttribute(AttributeFlags, Buffer, BufferSize, RequiredBufferSize)
+
+* CoCreateInstance::
+
+ CoCreateInstance(rclsid, pUnkOuter=None, dwClsContext=tagCLSCTX.CLSCTX_INPROC_SERVER(0x1L), riid=NeededParameter, ppv=NeededParameter)
+ Errcheck:
+ Nothing special
+
+* CoInitializeEx::
+
+ CoInitializeEx(pvReserved=None, dwCoInit=tagCOINIT.COINIT_MULTITHREADED(0x0L))
+ Errcheck:
+ Nothing special
+
+* CoInitializeSecurity::
+
+ CoInitializeSecurity(pSecDesc, cAuthSvc, asAuthSvc, pReserved1, dwAuthnLevel, dwImpLevel, pAuthList, dwCapabilities, pReserved3)
+ Errcheck:
+ Nothing special
+
+* CreateFileA::
+
+ CreateFileA(lpFileName, dwDesiredAccess=GENERIC_READ(0x80000000L), dwShareMode=0, lpSecurityAttributes=None, dwCreationDisposition=OPEN_EXISTING(0x3L), dwFlagsAndAttributes=FILE_ATTRIBUTE_NORMAL(0x80L), hTemplateFile=None)
+ Errcheck:
+ raise Kernel32Error if result is NOT 0
+
+* CreateFileMappingA::
+
+ CreateFileMappingA(hFile, lpFileMappingAttributes=None, flProtect=PAGE_READWRITE(0x4L), dwMaximumSizeHigh=0, dwMaximumSizeLow=NeededParameter, lpName=NeededParameter)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* CreateFileMappingW::
+
+ CreateFileMappingW(hFile, lpFileMappingAttributes=None, flProtect=PAGE_READWRITE(0x4L), dwMaximumSizeHigh=0, dwMaximumSizeLow=0, lpName=NeededParameter)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* CreateFileW::
+
+ CreateFileW(lpFileName, dwDesiredAccess=GENERIC_READ(0x80000000L), dwShareMode=0, lpSecurityAttributes=None, dwCreationDisposition=OPEN_EXISTING(0x3L), dwFlagsAndAttributes=FILE_ATTRIBUTE_NORMAL(0x80L), hTemplateFile=None)
+ Errcheck:
+ raise Kernel32Error if result is NOT 0
+
+* CreateProcessA::
+
+ CreateProcessA(lpApplicationName, lpCommandLine=None, lpProcessAttributes=None, lpThreadAttributes=None, bInheritHandles=False, dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None, lpProcessInformation=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* CreateProcessW::
+
+ CreateProcessW(lpApplicationName, lpCommandLine=None, lpProcessAttributes=None, lpThreadAttributes=None, bInheritHandles=False, dwCreationFlags=0, lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None, lpProcessInformation=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* CreateRemoteThread::
+
+ CreateRemoteThread(hProcess=NeededParameter, lpThreadAttributes=None, dwStackSize=0, lpStartAddress=NeededParameter, lpParameter=NeededParameter, dwCreationFlags=0, lpThreadId=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* CreateThread::
+
+ CreateThread(lpThreadAttributes=None, dwStackSize=0, lpStartAddress=NeededParameter, lpParameter=NeededParameter, dwCreationFlags=0, lpThreadId=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* CreateToolhelp32Snapshot::
+
+ CreateToolhelp32Snapshot(dwFlags, th32ProcessID=0)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* CryptCATAdminAcquireContext::
+
+ CryptCATAdminAcquireContext(phCatAdmin, pgSubsystem, dwFlags)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* CryptCATAdminCalcHashFromFileHandle::
+
+ CryptCATAdminCalcHashFromFileHandle(hFile, pcbHash, pbHash, dwFlags)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* CryptCATAdminEnumCatalogFromHash::
+
+ CryptCATAdminEnumCatalogFromHash(hCatAdmin, pbHash, cbHash, dwFlags, phPrevCatInfo)
+ Errcheck:
+ Nothing special
+
+* CryptCATAdminReleaseCatalogContext::
+
+ CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, dwFlags)
+ Errcheck:
+ Nothing special
+
+* CryptCATAdminReleaseContext::
+
+ CryptCATAdminReleaseContext(hCatAdmin, dwFlags)
+ Errcheck:
+ Nothing special
+
+* CryptCATCatalogInfoFromContext::
+
+ CryptCATCatalogInfoFromContext(hCatInfo, psCatInfo, dwFlags)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* DeviceIoControl::
+
+ DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize=None, lpOutBuffer=NeededParameter, nOutBufferSize=None, lpBytesReturned=None, lpOverlapped=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* DuplicateHandle::
+
+ DuplicateHandle(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, lpTargetHandle, dwDesiredAccess=0, bInheritHandle=False, dwOptions=0)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* EnumServicesStatusExA::
+
+ EnumServicesStatusExA(hSCManager, InfoLevel, dwServiceType, dwServiceState, lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle, pszGroupName)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* EnumServicesStatusExW::
+
+ EnumServicesStatusExW(hSCManager, InfoLevel, dwServiceType, dwServiceState, lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle, pszGroupName)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetExtendedTcpTable::
+
+ GetExtendedTcpTable(pTcpTable, pdwSize=None, bOrder=True, ulAf=NeededParameter, TableClass=_TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL(0x5L), Reserved=0)
+ Errcheck:
+ raise IphlpapiError if result is NOT 0
+
+* GetFileVersionInfoA::
+
+ GetFileVersionInfoA(lptstrFilename, dwHandle=0, dwLen=None, lpData=NeededParameter)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetFileVersionInfoSizeA::
+
+ GetFileVersionInfoSizeA(lptstrFilename, lpdwHandle=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetFileVersionInfoSizeW::
+
+ GetFileVersionInfoSizeW(lptstrFilename, lpdwHandle=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetFileVersionInfoW::
+
+ GetFileVersionInfoW(lptstrFilename, dwHandle=0, dwLen=None, lpData=NeededParameter)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetIfTable::
+
+ GetIfTable(pIfTable, pdwSize, bOrder=False)
+ Errcheck:
+ raise IphlpapiError if result is NOT 0
+
+* GetInterfaceInfo::
+
+ GetInterfaceInfo(pIfTable, dwOutBufLen=None)
+ Errcheck:
+ raise IphlpapiError if result is NOT 0
+
+* GetIpAddrTable::
+
+ GetIpAddrTable(pIpAddrTable, pdwSize, bOrder=False)
+ Errcheck:
+ raise IphlpapiError if result is NOT 0
+
+* GetMappedFileNameAWrapper::
+
+ GetMappedFileNameAWrapper(hProcess, lpv, lpFilename, nSize=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetMappedFileNameAWrapper::
+
+ GetMappedFileNameAWrapper(hProcess, lpv, lpFilename, nSize=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetMappedFileNameWWrapper::
+
+ GetMappedFileNameWWrapper(hProcess, lpv, lpFilename, nSize=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetMappedFileNameWWrapper::
+
+ GetMappedFileNameWWrapper(hProcess, lpv, lpFilename, nSize=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetModuleBaseNameAWrapper::
+
+ GetModuleBaseNameAWrapper(hProcess, hModule, lpBaseName, nSize=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetModuleBaseNameAWrapper::
+
+ GetModuleBaseNameAWrapper(hProcess, hModule, lpBaseName, nSize=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetModuleBaseNameWWrapper::
+
+ GetModuleBaseNameWWrapper(hProcess, hModule, lpBaseName, nSize=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetModuleBaseNameWWrapper::
+
+ GetModuleBaseNameWWrapper(hProcess, hModule, lpBaseName, nSize=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetProcessImageFileNameAWrapper::
+
+ GetProcessImageFileNameAWrapper(hProcess, lpImageFileName, nSize=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetProcessImageFileNameAWrapper::
+
+ GetProcessImageFileNameAWrapper(hProcess, lpImageFileName, nSize=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetProcessImageFileNameWWrapper::
+
+ GetProcessImageFileNameWWrapper(hProcess, lpImageFileName, nSize=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetProcessImageFileNameWWrapper::
+
+ GetProcessImageFileNameWWrapper(hProcess, lpImageFileName, nSize=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetProcessTimes::
+
+ GetProcessTimes(hProcess, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetThreadContext::
+
+ GetThreadContext(hThread, lpContext=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetTokenInformation::
+
+ GetTokenInformation(TokenHandle=NeededParameter, TokenInformationClass=NeededParameter, TokenInformation=None, TokenInformationLength=0, ReturnLength=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetVolumeInformationA::
+
+ GetVolumeInformationA(lpRootPathName, lpVolumeNameBuffer, nVolumeNameSize, lpVolumeSerialNumber, lpMaximumComponentLength, lpFileSystemFlags, lpFileSystemNameBuffer, nFileSystemNameSize)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* GetVolumeInformationW::
+
+ GetVolumeInformationW(lpRootPathName, lpVolumeNameBuffer=None, nVolumeNameSize=0, lpVolumeSerialNumber=None, lpMaximumComponentLength=None, lpFileSystemFlags=None, lpFileSystemNameBuffer=None, nFileSystemNameSize=0)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* LdrLoadDll::
+
+ LdrLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle)
+
+* LookupAccountSidA::
+
+ LookupAccountSidA(lpSystemName, lpSid, lpName, cchName, lpReferencedDomainName, cchReferencedDomainName, peUse)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* LookupAccountSidW::
+
+ LookupAccountSidW(lpSystemName, lpSid, lpName, cchName, lpReferencedDomainName, cchReferencedDomainName, peUse)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* LookupPrivilegeValueA::
+
+ LookupPrivilegeValueA(lpSystemName=None, lpName=NeededParameter, lpLuid=NeededParameter)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* LookupPrivilegeValueW::
+
+ LookupPrivilegeValueW(lpSystemName=None, lpName=NeededParameter, lpLuid=NeededParameter)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* MapViewOfFile::
+
+ MapViewOfFile(hFileMappingObject, dwDesiredAccess=FILE_MAP_ALL_ACCESS(0xf001fL), dwFileOffsetHigh=0, dwFileOffsetLow=0, dwNumberOfBytesToMap=NeededParameter)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* NtAlpcAcceptConnectPort::
+
+ NtAlpcAcceptConnectPort(PortHandle, ConnectionPortHandle, Flags, ObjectAttributes, PortAttributes, PortContext, ConnectionRequest, ConnectionMessageAttributes, AcceptConnection)
+
+* NtAlpcConnectPort::
+
+ NtAlpcConnectPort(PortHandle, PortName, ObjectAttributes, PortAttributes, Flags, RequiredServerSid, ConnectionMessage, BufferLength, OutMessageAttributes, InMessageAttributes, Timeout)
+
+* NtAlpcCreatePort::
+
+ NtAlpcCreatePort(PortHandle, ObjectAttributes, PortAttributes)
+
+* NtAlpcSendWaitReceivePort::
+
+ NtAlpcSendWaitReceivePort(PortHandle, Flags, SendMessage, SendMessageAttributes, ReceiveMessage, BufferLength, ReceiveMessageAttributes, Timeout)
+
+* NtCreateThreadEx::
+
+ NtCreateThreadEx(ThreadHandle=None, DesiredAccess=2097151, ObjectAttributes=0, ProcessHandle=NeededParameter, lpStartAddress=NeededParameter, lpParameter=NeededParameter, CreateSuspended=0, dwStackSize=0, Unknown1=0, Unknown2=0, Unknown=0)
+
+* NtGetContextThread::
+
+ NtGetContextThread(hThread, lpContext)
+
+* NtOpenDirectoryObject::
+
+ NtOpenDirectoryObject(DirectoryHandle, DesiredAccess, ObjectAttributes)
+
+* NtOpenEvent::
+
+ NtOpenEvent(EventHandle, DesiredAccess, ObjectAttributes)
+
+* NtOpenSymbolicLinkObject::
+
+ NtOpenSymbolicLinkObject(LinkHandle, DesiredAccess, ObjectAttributes)
+
+* NtProtectVirtualMemory::
+
+ NtProtectVirtualMemory(ProcessHandle, BaseAddress, NumberOfBytesToProtect, NewAccessProtection, OldAccessProtection=None)
+
+* NtQueryDirectoryObject::
+
+ NtQueryDirectoryObject(DirectoryHandle, Buffer, Length, ReturnSingleEntry, RestartScan, Context, ReturnLength)
+
+* NtQueryInformationProcess::
+
+ NtQueryInformationProcess(ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength=0, ReturnLength=None)
+
+* NtQueryInformationThread::
+
+ NtQueryInformationThread(ThreadHandle, ThreadInformationClass, ThreadInformation, ThreadInformationLength=0, ReturnLength=None)
+
+* NtQueryObject::
+
+ NtQueryObject(Handle, ObjectInformationClass, ObjectInformation=None, ObjectInformationLength=0, ReturnLength=NeededParameter)
+
+* NtQuerySymbolicLinkObject::
+
+ NtQuerySymbolicLinkObject(LinkHandle, LinkTarget, ReturnedLength)
+
+* NtQuerySystemInformation::
+
+ NtQuerySystemInformation(SystemInformationClass, SystemInformation=None, SystemInformationLength=0, ReturnLength=NeededParameter)
+
+* NtQueryVirtualMemory::
+
+ NtQueryVirtualMemory(ProcessHandle, BaseAddress, MemoryInformationClass, MemoryInformation=NeededParameter, MemoryInformationLength=0, ReturnLength=None)
+
+* NtSetContextThread::
+
+ NtSetContextThread(hThread, lpContext)
+
+* NtWow64ReadVirtualMemory64::
+
+ NtWow64ReadVirtualMemory64(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead=None)
+
+* NtWow64WriteVirtualMemory64::
+
+ NtWow64WriteVirtualMemory64(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesWritten=None)
+
+* OpenEventA::
+
+ OpenEventA(dwDesiredAccess, bInheritHandle, lpName)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* OpenEventW::
+
+ OpenEventW(dwDesiredAccess, bInheritHandle, lpName)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* OpenProcess::
+
+ OpenProcess(dwDesiredAccess=PROCESS_ALL_ACCESS(0x1f0fffL), bInheritHandle=0, dwProcessId=NeededParameter)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* OpenProcessToken::
+
+ OpenProcessToken(ProcessHandle=None, DesiredAccess=NeededParameter, TokenHandle=NeededParameter)
+ If ProcessHandle is None: take the current process
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* OpenSCManagerA::
+
+ OpenSCManagerA(lpMachineName=None, lpDatabaseName=None, dwDesiredAccess=SC_MANAGER_ALL_ACCESS(0xf003fL))
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* OpenSCManagerW::
+
+ OpenSCManagerW(lpMachineName=None, lpDatabaseName=None, dwDesiredAccess=SC_MANAGER_ALL_ACCESS(0xf003fL))
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* OpenThread::
+
+ OpenThread(dwDesiredAccess=THREAD_ALL_ACCESS(0x1f03ffL), bInheritHandle=0, dwThreadId=NeededParameter)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* Process32First::
+
+ Process32First(hSnapshot, lpte)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* Process32Next::
+
+ Process32Next(hSnapshot, lpte)
+ Errcheck:
+ Nothing special
+
+* QueryWorkingSetWrapper::
+
+ QueryWorkingSetWrapper(hProcess, pv, cb)
+ Errcheck:
+ raise Kernel32Error if result is 0
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* QueryWorkingSetExWrapper::
+
+ QueryWorkingSetExWrapper(hProcess, pv, cb)
+ Errcheck:
+ raise Kernel32Error if result is 0
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* QueryWorkingSetExWrapper::
+
+ QueryWorkingSetExWrapper(hProcess, pv, cb)
+ Errcheck:
+ raise Kernel32Error if result is 0
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* QueryWorkingSetWrapper::
+
+ QueryWorkingSetWrapper(hProcess, pv, cb)
+ Errcheck:
+ raise Kernel32Error if result is 0
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* ReadProcessMemory::
+
+ ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* RegCloseKey::
+
+ RegCloseKey(hKey)
+ Errcheck:
+ raise Kernel32Error if result is NOT 0
+
+* RegGetValueA::
+
+ RegGetValueA(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData)
+ Errcheck:
+ raise Kernel32Error if result is NOT 0
+
+* RegGetValueW::
+
+ RegGetValueW(hkey, lpSubKey=None, lpValue=NeededParameter, dwFlags=0, pdwType=None, pvData=None, pcbData=None)
+ Errcheck:
+ raise Kernel32Error if result is NOT 0
+
+* RegOpenKeyExA::
+
+ RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, phkResult)
+ Errcheck:
+ raise Kernel32Error if result is NOT 0
+
+* RegOpenKeyExW::
+
+ RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, phkResult)
+ Errcheck:
+ raise Kernel32Error if result is NOT 0
+
+* RemoveVectoredExceptionHandler::
+
+ RemoveVectoredExceptionHandler(Handler)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* SetThreadAffinityMask::
+
+ SetThreadAffinityMask(hThread=None, dwThreadAffinityMask=NeededParameter)
+ If hThread is not given, it will be the current thread
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* SetThreadContext::
+
+ SetThreadContext(hThread, lpContext)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* Thread32First::
+
+ Thread32First(hSnapshot, lpte)
+ Set byref(lpte) if needed
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* Thread32Next::
+
+ Thread32Next(hSnapshot, lpte)
+ Set byref(lpte) if needed
+ Errcheck:
+ Nothing special
+
+* VerQueryValueA::
+
+ VerQueryValueA(pBlock, lpSubBlock, lplpBuffer, puLen)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* VerQueryValueW::
+
+ VerQueryValueW(pBlock, lpSubBlock, lplpBuffer, puLen)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* VirtualAlloc::
+
+ VirtualAlloc(lpAddress=0, dwSize=NeededParameter, flAllocationType=MEM_COMMIT(0x1000L), flProtect=PAGE_EXECUTE_READWRITE(0x40L))
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* VirtualAllocEx::
+
+ VirtualAllocEx(hProcess, lpAddress=0, dwSize=NeededParameter, flAllocationType=MEM_COMMIT(0x1000L), flProtect=PAGE_EXECUTE_READWRITE(0x40L))
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* VirtualFree::
+
+ VirtualFree(lpAddress, dwSize=0, dwFreeType=MEM_RELEASE(0x8000L))
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* VirtualFreeEx::
+
+ VirtualFreeEx(hProcess, lpAddress, dwSize=0, dwFreeType=MEM_RELEASE(0x8000L))
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* VirtualProtect::
+
+ VirtualProtect(lpAddress, dwSize, flNewProtect, lpflOldProtect=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* VirtualProtectEx::
+
+ VirtualProtectEx(hProcess, lpAddress, dwSize, flNewProtect, lpflOldProtect=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* WaitForDebugEvent::
+
+ WaitForDebugEvent(lpDebugEvent, dwMilliseconds=INFINITE(0xffffffffL))
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* WaitForSingleObject::
+
+ WaitForSingleObject(hHandle, dwMilliseconds=INFINITE(0xffffffffL))
+ Errcheck:
+ raise Kernel32Error if result is NOT 0
+
+* WinVerifyTrust::
+
+ WinVerifyTrust(hwnd, pgActionID, pWVTData)
+ Errcheck:
+ Nothing special
+
+* Wow64SetThreadContext::
+
+ Wow64SetThreadContext(hThread, lpContext)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* WriteFile::
+
+ WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite=None, lpNumberOfBytesWritten=None, lpOverlapped=None)
+ Errcheck:
+ raise Kernel32Error if result is 0
+
+* WriteProcessMemory::
+
+ WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize=None, lpNumberOfBytesWritten=None)
+ Computer nSize with len(lpBuffer) if not given
+ Errcheck:
+ raise Kernel32Error if result is 0
\ No newline at end of file
diff --git a/docs/source/wintrust.rst b/docs/source/wintrust.rst
new file mode 100644
index 0000000..5d230b4
--- /dev/null
+++ b/docs/source/wintrust.rst
@@ -0,0 +1,40 @@
+``windows.wintrust`` -- Checking signature
+******************************************
+
+.. module:: windows.wintrust
+
+.. note::
+
+ See sample :ref:`sample_wintrust`
+
+The :mod:`wintrust` module offers wrapper around ``wintrust.dll``.
+It allows to check the signature of a file.
+
+The signature of a file can be at two differents place:
+
+ * In the file itself (:func:`check_signature`)
+ * In a catalog file (:func:`full_signature_information`)
+
+.. note::
+
+ `Explanation about catalog files `_
+
+
+API
+"""
+
+.. autofunction:: is_signed
+
+.. autofunction:: full_signature_information
+
+.. autofunction:: check_signature
+
+
+SignatureData
+'''''''''''''
+
+.. autoclass:: SignatureData
+ :exclude-members: count, index
+
+
+
diff --git a/docs/source/wip.rst b/docs/source/wip.rst
new file mode 100644
index 0000000..33437e9
--- /dev/null
+++ b/docs/source/wip.rst
@@ -0,0 +1,6 @@
+Early Work In Progress
+======================
+
+Here are some features that are still work in progress. Code might be unstable and/or ultra-ugly.
+
+
\ No newline at end of file
diff --git a/docs/source/wmi.rst b/docs/source/wmi.rst
new file mode 100644
index 0000000..f7b41b3
--- /dev/null
+++ b/docs/source/wmi.rst
@@ -0,0 +1,10 @@
+WMI -- Make request to WMI
+==========================
+
+.. module:: windows.winobject.wmi
+
+.. note::
+
+ See sample :ref:`wmi_request`
+
+.. autoclass:: WmiRequester
\ No newline at end of file