text:
#ifndef QGLFUNCTIONS_H
#define QGLFUNCTIONS_H

#include <QtOpenGL/qgl.h>
#include <QtGui/qopenglcontext.h>
#include <QtGui/qopenglfunctions.h>

QT_BEGIN_NAMESPACE

struct QGLFunctionsPrivate;

class Q_OPENGL_EXPORT QGLFunctions
{
public:
    QGLFunctions();
    explicit QGLFunctions(const QGLContext *context);
    ~QGLFunctions() {}

    enum OpenGLFeature
    {
        Multitexture          = 0x0001,
        Shaders               = 0x0002,
        Buffers               = 0x0004,
        Framebuffers          = 0x0008,
        BlendColor            = 0x0010,
        BlendEquation         = 0x0020,
        BlendEquationSeparate = 0x0040,
        BlendFuncSeparate     = 0x0080,
        BlendSubtract         = 0x0100,
        CompressedTextures    = 0x0200,
        Multisample           = 0x0400,
        StencilSeparate       = 0x0800,
        NPOTTextures          = 0x1000
    };
    Q_DECLARE_FLAGS(OpenGLFeatures, OpenGLFeature)

    QGLFunctions::OpenGLFeatures openGLFeatures() const;
    bool hasOpenGLFeature(QGLFunctions::OpenGLFeature feature) const;

    void initializeGLFunctions(const QGLContext *context = 0);

    void glActiveTexture(GLenum texture);
    void glAttachShader(GLuint program, GLuint shader);
    void glBindAttribLocation(GLuint program, GLuint index, const char* name);
    void glBindBuffer(GLenum target, GLuint buffer);
    void glBindFramebuffer(GLenum target, GLuint framebuffer);
    void glBindRenderbuffer(GLenum target, GLuint renderbuffer);
    void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
    void glBlendEquation(GLenum mode);
    void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
    void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
    void glBufferData(GLenum target, qopengl_GLsizeiptr size, const void* data, GLenum usage);
    void glBufferSubData(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr size, const void* data);
    GLenum glCheckFramebufferStatus(GLenum target);
    void glClearDepthf(GLclampf depth);
    void glCompileShader(GLuint shader);
    void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
    void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
    GLuint glCreateProgram();
    GLuint glCreateShader(GLenum type);
    void glDeleteBuffers(GLsizei n, const GLuint* buffers);
    void glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
    void glDeleteProgram(GLuint program);
    void glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers);
    void glDeleteShader(GLuint shader);
    void glDepthRangef(GLclampf zNear, GLclampf zFar);
    void glDetachShader(GLuint program, GLuint shader);
    void glDisableVertexAttribArray(GLuint index);
    void glEnableVertexAttribArray(GLuint index);
    void glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
    void glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
    void glGenBuffers(GLsizei n, GLuint* buffers);
    void glGenerateMipmap(GLenum target);
    void glGenFramebuffers(GLsizei n, GLuint* framebuffers);
    void glGenRenderbuffers(GLsizei n, GLuint* renderbuffers);
    void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
    void glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
    void glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
    int glGetAttribLocation(GLuint program, const char* name);
    void glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params);
    void glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params);
    void glGetProgramiv(GLuint program, GLenum pname, GLint* params);
    void glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog);
    void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params);
    void glGetShaderiv(GLuint shader, GLenum pname, GLint* params);
    void glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog);
    void glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
    void glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source);
    void glGetUniformfv(GLuint program, GLint location, GLfloat* params);
    void glGetUniformiv(GLuint program, GLint location, GLint* params);
    int glGetUniformLocation(GLuint program, const char* name);
    void glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
    void glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
    void glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer);
    GLboolean glIsBuffer(GLuint buffer);
    GLboolean glIsFramebuffer(GLuint framebuffer);
    GLboolean glIsProgram(GLuint program);
    GLboolean glIsRenderbuffer(GLuint renderbuffer);
    GLboolean glIsShader(GLuint shader);
    void glLinkProgram(GLuint program);
    void glReleaseShaderCompiler();
    void glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
    void glSampleCoverage(GLclampf value, GLboolean invert);
    void glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length);
    void glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length);
    void glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
    void glStencilMaskSeparate(GLenum face, GLuint mask);
    void glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
    void glUniform1f(GLint location, GLfloat x);
    void glUniform1fv(GLint location, GLsizei count, const GLfloat* v);
    void glUniform1i(GLint location, GLint x);
    void glUniform1iv(GLint location, GLsizei count, const GLint* v);
    void glUniform2f(GLint location, GLfloat x, GLfloat y);
    void glUniform2fv(GLint location, GLsizei count, const GLfloat* v);
    void glUniform2i(GLint location, GLint x, GLint y);
    void glUniform2iv(GLint location, GLsizei count, const GLint* v);
    void glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z);
    void glUniform3fv(GLint location, GLsizei count, const GLfloat* v);
    void glUniform3i(GLint location, GLint x, GLint y, GLint z);
    void glUniform3iv(GLint location, GLsizei count, const GLint* v);
    void glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
    void glUniform4fv(GLint location, GLsizei count, const GLfloat* v);
    void glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w);
    void glUniform4iv(GLint location, GLsizei count, const GLint* v);
    void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
    void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
    void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
    void glUseProgram(GLuint program);
    void glValidateProgram(GLuint program);
    void glVertexAttrib1f(GLuint indx, GLfloat x);
    void glVertexAttrib1fv(GLuint indx, const GLfloat* values);
    void glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y);
    void glVertexAttrib2fv(GLuint indx, const GLfloat* values);
    void glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
    void glVertexAttrib3fv(GLuint indx, const GLfloat* values);
    void glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
    void glVertexAttrib4fv(GLuint indx, const GLfloat* values);
    void glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr);

private:
    QGLFunctionsPrivate *d_ptr;
    static bool isInitialized(const QGLFunctionsPrivate *d) { return d != 0; }
};

Q_DECLARE_OPERATORS_FOR_FLAGS(QGLFunctions::OpenGLFeatures)

struct QGLFunctionsPrivate
{
    QGLFunctionsPrivate(const QGLContext *context = 0);
    QOpenGLFunctions *funcs;
};

inline void QGLFunctions::glActiveTexture(GLenum texture)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glActiveTexture(texture);
}

inline void QGLFunctions::glAttachShader(GLuint program, GLuint shader)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glAttachShader(program, shader);
}

inline void QGLFunctions::glBindAttribLocation(GLuint program, GLuint index, const char* name)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glBindAttribLocation(program, index, name);
}

inline void QGLFunctions::glBindBuffer(GLenum target, GLuint buffer)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glBindBuffer(target, buffer);
}

inline void QGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffer)
{
    if (framebuffer == 0)
        framebuffer = QOpenGLContext::currentContext()->defaultFramebufferObject();
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glBindFramebuffer(target, framebuffer);
}

inline void QGLFunctions::glBindRenderbuffer(GLenum target, GLuint renderbuffer)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glBindRenderbuffer(target, renderbuffer);
}

inline void QGLFunctions::glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glBlendColor(red, green, blue, alpha);
}

inline void QGLFunctions::glBlendEquation(GLenum mode)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glBlendEquation(mode);
}

inline void QGLFunctions::glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glBlendEquationSeparate(modeRGB, modeAlpha);
}

inline void QGLFunctions::glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
}

inline void QGLFunctions::glBufferData(GLenum target, qopengl_GLsizeiptr size, const void* data, GLenum usage)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glBufferData(target, size, data, usage);
}

inline void QGLFunctions::glBufferSubData(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr size, const void* data)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glBufferSubData(target, offset, size, data);
}

inline GLenum QGLFunctions::glCheckFramebufferStatus(GLenum target)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    return d_ptr->funcs->glCheckFramebufferStatus(target);
}

inline void QGLFunctions::glClearDepthf(GLclampf depth)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    return d_ptr->funcs->glClearDepthf(depth);
}

inline void QGLFunctions::glCompileShader(GLuint shader)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glCompileShader(shader);
}

inline void QGLFunctions::glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
}

inline void QGLFunctions::glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
}

inline GLuint QGLFunctions::glCreateProgram()
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    return d_ptr->funcs->glCreateProgram();
}

inline GLuint QGLFunctions::glCreateShader(GLenum type)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    return d_ptr->funcs->glCreateShader(type);
}

inline void QGLFunctions::glDeleteBuffers(GLsizei n, const GLuint* buffers)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glDeleteBuffers(n, buffers);
}

inline void QGLFunctions::glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glDeleteFramebuffers(n, framebuffers);
}

inline void QGLFunctions::glDeleteProgram(GLuint program)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glDeleteProgram(program);
}

inline void QGLFunctions::glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glDeleteRenderbuffers(n, renderbuffers);
}

inline void QGLFunctions::glDeleteShader(GLuint shader)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glDeleteShader(shader);
}

inline void QGLFunctions::glDepthRangef(GLclampf zNear, GLclampf zFar)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    return d_ptr->funcs->glDepthRangef(zNear, zFar);
}

inline void QGLFunctions::glDetachShader(GLuint program, GLuint shader)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glDetachShader(program, shader);
}

inline void QGLFunctions::glDisableVertexAttribArray(GLuint index)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glDisableVertexAttribArray(index);
}

inline void QGLFunctions::glEnableVertexAttribArray(GLuint index)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glEnableVertexAttribArray(index);
}

inline void QGLFunctions::glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
}

inline void QGLFunctions::glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glFramebufferTexture2D(target, attachment, textarget, texture, level);
}

inline void QGLFunctions::glGenBuffers(GLsizei n, GLuint* buffers)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGenBuffers(n, buffers);
}

inline void QGLFunctions::glGenerateMipmap(GLenum target)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGenerateMipmap(target);
}

inline void QGLFunctions::glGenFramebuffers(GLsizei n, GLuint* framebuffers)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGenFramebuffers(n, framebuffers);
}

inline void QGLFunctions::glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGenRenderbuffers(n, renderbuffers);
}

inline void QGLFunctions::glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGetActiveAttrib(program, index, bufsize, length, size, type, name);
}

inline void QGLFunctions::glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGetActiveUniform(program, index, bufsize, length, size, type, name);
}

inline void QGLFunctions::glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGetAttachedShaders(program, maxcount, count, shaders);
}

inline int QGLFunctions::glGetAttribLocation(GLuint program, const char* name)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    return d_ptr->funcs->glGetAttribLocation(program, name);
}

inline void QGLFunctions::glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGetBufferParameteriv(target, pname, params);
}

inline void QGLFunctions::glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);
}

inline void QGLFunctions::glGetProgramiv(GLuint program, GLenum pname, GLint* params)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGetProgramiv(program, pname, params);
}

inline void QGLFunctions::glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGetProgramInfoLog(program, bufsize, length, infolog);
}

inline void QGLFunctions::glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGetRenderbufferParameteriv(target, pname, params);
}

inline void QGLFunctions::glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGetShaderiv(shader, pname, params);
}

inline void QGLFunctions::glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGetShaderInfoLog(shader, bufsize, length, infolog);
}

inline void QGLFunctions::glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
}

inline void QGLFunctions::glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGetShaderSource(shader, bufsize, length, source);
}

inline void QGLFunctions::glGetUniformfv(GLuint program, GLint location, GLfloat* params)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGetUniformfv(program, location, params);
}

inline void QGLFunctions::glGetUniformiv(GLuint program, GLint location, GLint* params)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGetUniformiv(program, location, params);
}

inline int QGLFunctions::glGetUniformLocation(GLuint program, const char* name)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    return d_ptr->funcs->glGetUniformLocation(program, name);
}

inline void QGLFunctions::glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGetVertexAttribfv(index, pname, params);
}

inline void QGLFunctions::glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGetVertexAttribiv(index, pname, params);
}

inline void QGLFunctions::glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glGetVertexAttribPointerv(index, pname, pointer);
}

inline GLboolean QGLFunctions::glIsBuffer(GLuint buffer)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    return d_ptr->funcs->glIsBuffer(buffer);
}

inline GLboolean QGLFunctions::glIsFramebuffer(GLuint framebuffer)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    return d_ptr->funcs->glIsFramebuffer(framebuffer);
}

inline GLboolean QGLFunctions::glIsProgram(GLuint program)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    return d_ptr->funcs->glIsProgram(program);
}

inline GLboolean QGLFunctions::glIsRenderbuffer(GLuint renderbuffer)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    return d_ptr->funcs->glIsRenderbuffer(renderbuffer);
}

inline GLboolean QGLFunctions::glIsShader(GLuint shader)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    return d_ptr->funcs->glIsShader(shader);
}

inline void QGLFunctions::glLinkProgram(GLuint program)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glLinkProgram(program);
}

inline void QGLFunctions::glReleaseShaderCompiler()
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glReleaseShaderCompiler();
}

inline void QGLFunctions::glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glRenderbufferStorage(target, internalformat, width, height);
}

inline void QGLFunctions::glSampleCoverage(GLclampf value, GLboolean invert)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glSampleCoverage(value, invert);
}

inline void QGLFunctions::glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glShaderBinary(n, shaders, binaryformat, binary, length);
}

inline void QGLFunctions::glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glShaderSource(shader, count, string, length);
}

inline void QGLFunctions::glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glStencilFuncSeparate(face, func, ref, mask);
}

inline void QGLFunctions::glStencilMaskSeparate(GLenum face, GLuint mask)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glStencilMaskSeparate(face, mask);
}

inline void QGLFunctions::glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glStencilOpSeparate(face, fail, zfail, zpass);
}

inline void QGLFunctions::glUniform1f(GLint location, GLfloat x)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniform1f(location, x);
}

inline void QGLFunctions::glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniform1fv(location, count, v);
}

inline void QGLFunctions::glUniform1i(GLint location, GLint x)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniform1i(location, x);
}

inline void QGLFunctions::glUniform1iv(GLint location, GLsizei count, const GLint* v)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniform1iv(location, count, v);
}

inline void QGLFunctions::glUniform2f(GLint location, GLfloat x, GLfloat y)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniform2f(location, x, y);
}

inline void QGLFunctions::glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniform2fv(location, count, v);
}

inline void QGLFunctions::glUniform2i(GLint location, GLint x, GLint y)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniform2i(location, x, y);
}

inline void QGLFunctions::glUniform2iv(GLint location, GLsizei count, const GLint* v)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniform2iv(location, count, v);
}

inline void QGLFunctions::glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniform3f(location, x, y, z);
}

inline void QGLFunctions::glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniform3fv(location, count, v);
}

inline void QGLFunctions::glUniform3i(GLint location, GLint x, GLint y, GLint z)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniform3i(location, x, y, z);
}

inline void QGLFunctions::glUniform3iv(GLint location, GLsizei count, const GLint* v)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniform3iv(location, count, v);
}

inline void QGLFunctions::glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniform4f(location, x, y, z, w);
}

inline void QGLFunctions::glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniform4fv(location, count, v);
}

inline void QGLFunctions::glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniform4i(location, x, y, z, w);
}

inline void QGLFunctions::glUniform4iv(GLint location, GLsizei count, const GLint* v)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniform4iv(location, count, v);
}

inline void QGLFunctions::glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniformMatrix2fv(location, count, transpose, value);
}

inline void QGLFunctions::glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniformMatrix3fv(location, count, transpose, value);
}

inline void QGLFunctions::glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUniformMatrix4fv(location, count, transpose, value);
}

inline void QGLFunctions::glUseProgram(GLuint program)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glUseProgram(program);
}

inline void QGLFunctions::glValidateProgram(GLuint program)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glValidateProgram(program);
}

inline void QGLFunctions::glVertexAttrib1f(GLuint indx, GLfloat x)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glVertexAttrib1f(indx, x);
}

inline void QGLFunctions::glVertexAttrib1fv(GLuint indx, const GLfloat* values)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glVertexAttrib1fv(indx, values);
}

inline void QGLFunctions::glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glVertexAttrib2f(indx, x, y);
}

inline void QGLFunctions::glVertexAttrib2fv(GLuint indx, const GLfloat* values)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glVertexAttrib2fv(indx, values);
}

inline void QGLFunctions::glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glVertexAttrib3f(indx, x, y, z);
}

inline void QGLFunctions::glVertexAttrib3fv(GLuint indx, const GLfloat* values)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glVertexAttrib3fv(indx, values);
}

inline void QGLFunctions::glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glVertexAttrib4f(indx, x, y, z, w);
}

inline void QGLFunctions::glVertexAttrib4fv(GLuint indx, const GLfloat* values)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glVertexAttrib4fv(indx, values);
}

inline void QGLFunctions::glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr)
{
    Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
    d_ptr->funcs->glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
}

#ifndef GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
#endif
#ifndef GL_ACTIVE_ATTRIBUTES
#define GL_ACTIVE_ATTRIBUTES 0x8B89
#endif
#ifndef GL_ACTIVE_TEXTURE
#define GL_ACTIVE_TEXTURE 0x84E0
#endif
#ifndef GL_ACTIVE_UNIFORM_MAX_LENGTH
#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
#endif
#ifndef GL_ACTIVE_UNIFORMS
#define GL_ACTIVE_UNIFORMS 0x8B86
#endif
#ifndef GL_ALIASED_LINE_WIDTH_RANGE
#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
#endif
#ifndef GL_ALIASED_POINT_SIZE_RANGE
#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
#endif
#ifndef GL_ALPHA
#define GL_ALPHA 0x1906
#endif
#ifndef GL_ALPHA_BITS
#define GL_ALPHA_BITS 0x0D55
#endif
#ifndef GL_ALWAYS
#define GL_ALWAYS 0x0207
#endif
#ifndef GL_ARRAY_BUFFER
#define GL_ARRAY_BUFFER 0x8892
#endif
#ifndef GL_ARRAY_BUFFER_BINDING
#define GL_ARRAY_BUFFER_BINDING 0x8894
#endif
#ifndef GL_ATTACHED_SHADERS
#define GL_ATTACHED_SHADERS 0x8B85
#endif
#ifndef GL_BACK
#define GL_BACK 0x0405
#endif
#ifndef GL_BLEND
#define GL_BLEND 0x0BE2
#endif
#ifndef GL_BLEND_COLOR
#define GL_BLEND_COLOR 0x8005
#endif
#ifndef GL_BLEND_DST_ALPHA
#define GL_BLEND_DST_ALPHA 0x80CA
#endif
#ifndef GL_BLEND_DST_RGB
#define GL_BLEND_DST_RGB 0x80C8
#endif
#ifndef GL_BLEND_EQUATION
#define GL_BLEND_EQUATION 0x8009
#endif
#ifndef GL_BLEND_EQUATION_ALPHA
#define GL_BLEND_EQUATION_ALPHA 0x883D
#endif
#ifndef GL_BLEND_EQUATION_RGB
#define GL_BLEND_EQUATION_RGB 0x8009
#endif
#ifndef GL_BLEND_SRC_ALPHA
#define GL_BLEND_SRC_ALPHA 0x80CB
#endif
#ifndef GL_BLEND_SRC_RGB
#define GL_BLEND_SRC_RGB 0x80C9
#endif
#ifndef GL_BLUE_BITS
#define GL_BLUE_BITS 0x0D54
#endif
#ifndef GL_BOOL
#define GL_BOOL 0x8B56
#endif
#ifndef GL_BOOL_VEC2
#define GL_BOOL_VEC2 0x8B57
#endif
#ifndef GL_BOOL_VEC3
#define GL_BOOL_VEC3 0x8B58
#endif
#ifndef GL_BOOL_VEC4
#define GL_BOOL_VEC4 0x8B59
#endif
#ifndef GL_BUFFER_SIZE
#define GL_BUFFER_SIZE 0x8764
#endif
#ifndef GL_BUFFER_USAGE
#define GL_BUFFER_USAGE 0x8765
#endif
#ifndef GL_BYTE
#define GL_BYTE 0x1400
#endif
#ifndef GL_CCW
#define GL_CCW 0x0901
#endif
#ifndef GL_CLAMP_TO_EDGE
#define GL_CLAMP_TO_EDGE 0x812F
#endif
#ifndef GL_COLOR_ATTACHMENT0
#define GL_COLOR_ATTACHMENT0 0x8CE0
#endif
#ifndef GL_COLOR_BUFFER_BIT
#define GL_COLOR_BUFFER_BIT 0x00004000
#endif
#ifndef GL_COLOR_CLEAR_VALUE
#define GL_COLOR_CLEAR_VALUE 0x0C22
#endif
#ifndef GL_COLOR_WRITEMASK
#define GL_COLOR_WRITEMASK 0x0C23
#endif
#ifndef GL_COMPILE_STATUS
#define GL_COMPILE_STATUS 0x8B81
#endif
#ifndef GL_COMPRESSED_TEXTURE_FORMATS
#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
#endif
#ifndef GL_CONSTANT_ALPHA
#define GL_CONSTANT_ALPHA 0x8003
#endif
#ifndef GL_CONSTANT_COLOR
#define GL_CONSTANT_COLOR 0x8001
#endif
#ifndef GL_CULL_FACE
#define GL_CULL_FACE 0x0B44
#endif
#ifndef GL_CULL_FACE_MODE
#define GL_CULL_FACE_MODE 0x0B45
#endif
#ifndef GL_CURRENT_PROGRAM
#define GL_CURRENT_PROGRAM 0x8B8D
#endif
#ifndef GL_CURRENT_VERTEX_ATTRIB
#define GL_CURRENT_VERTEX_ATTRIB 0x8626
#endif
#ifndef GL_CW
#define GL_CW 0x0900
#endif
#ifndef GL_DECR
#define GL_DECR 0x1E03
#endif
#ifndef GL_DECR_WRAP
#define GL_DECR_WRAP 0x8508
#endif
#ifndef GL_DELETE_STATUS
#define GL_DELETE_STATUS 0x8B80
#endif
#ifndef GL_DEPTH_ATTACHMENT
#define GL_DEPTH_ATTACHMENT 0x8D00
#endif
#ifndef GL_DEPTH_BITS
#define GL_DEPTH_BITS 0x0D56
#endif
#ifndef GL_DEPTH_BUFFER_BIT
#define GL_DEPTH_BUFFER_BIT 0x00000100
#endif
#ifndef GL_DEPTH_CLEAR_VALUE
#define GL_DEPTH_CLEAR_VALUE 0x0B73
#endif
#ifndef GL_DEPTH_COMPONENT
#define GL_DEPTH_COMPONENT 0x1902
#endif
#ifndef GL_DEPTH_COMPONENT16
#define GL_DEPTH_COMPONENT16 0x81A5
#endif
#ifndef GL_DEPTH_FUNC
#define GL_DEPTH_FUNC 0x0B74
#endif
#ifndef GL_DEPTH_RANGE
#define GL_DEPTH_RANGE 0x0B70
#endif
#ifndef GL_DEPTH_TEST
#define GL_DEPTH_TEST 0x0B71
#endif
#ifndef GL_DEPTH_WRITEMASK
#define GL_DEPTH_WRITEMASK 0x0B72
#endif
#ifndef GL_DITHER
#define GL_DITHER 0x0BD0
#endif
#ifndef GL_DONT_CARE
#define GL_DONT_CARE 0x1100
#endif
#ifndef GL_DST_ALPHA
#define GL_DST_ALPHA 0x0304
#endif
#ifndef GL_DST_COLOR
#define GL_DST_COLOR 0x0306
#endif
#ifndef GL_DYNAMIC_DRAW
#define GL_DYNAMIC_DRAW 0x88E8
#endif
#ifndef GL_ELEMENT_ARRAY_BUFFER
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
#endif
#ifndef GL_ELEMENT_ARRAY_BUFFER_BINDING
#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
#endif
#ifndef GL_EQUAL
#define GL_EQUAL 0x0202
#endif
#ifndef GL_EXTENSIONS
#define GL_EXTENSIONS 0x1F03
#endif
#ifndef GL_FALSE
#define GL_FALSE 0
#endif
#ifndef GL_FASTEST
#define GL_FASTEST 0x1101
#endif
#ifndef GL_FIXED
#define GL_FIXED 0x140C
#endif
#ifndef GL_FLOAT
#define GL_FLOAT 0x1406
#endif
#ifndef GL_FLOAT_MAT2
#define GL_FLOAT_MAT2 0x8B5A
#endif
#ifndef GL_FLOAT_MAT3
#define GL_FLOAT_MAT3 0x8B5B
#endif
#ifndef GL_FLOAT_MAT4
#define GL_FLOAT_MAT4 0x8B5C
#endif
#ifndef GL_FLOAT_VEC2
#define GL_FLOAT_VEC2 0x8B50
#endif
#ifndef GL_FLOAT_VEC3
#define GL_FLOAT_VEC3 0x8B51
#endif
#ifndef GL_FLOAT_VEC4
#define GL_FLOAT_VEC4 0x8B52
#endif
#ifndef GL_FRAGMENT_SHADER
#define GL_FRAGMENT_SHADER 0x8B30
#endif
#ifndef GL_FRAMEBUFFER
#define GL_FRAMEBUFFER 0x8D40
#endif
#ifndef GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
#endif
#ifndef GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
#endif
#ifndef GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
#endif
#ifndef GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
#endif
#ifndef GL_FRAMEBUFFER_BINDING
#define GL_FRAMEBUFFER_BINDING 0x8CA6
#endif
#ifndef GL_FRAMEBUFFER_COMPLETE
#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
#endif
#ifndef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
#endif
#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
#endif
#ifndef GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
#endif
#ifndef GL_FRAMEBUFFER_UNSUPPORTED
#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
#endif
#ifndef GL_FRONT
#define GL_FRONT 0x0404
#endif
#ifndef GL_FRONT_AND_BACK
#define GL_FRONT_AND_BACK 0x0408
#endif
#ifndef GL_FRONT_FACE
#define GL_FRONT_FACE 0x0B46
#endif
#ifndef GL_FUNC_ADD
#define GL_FUNC_ADD 0x8006
#endif
#ifndef GL_FUNC_REVERSE_SUBTRACT
#define GL_FUNC_REVERSE_SUBTRACT 0x800B
#endif
#ifndef GL_FUNC_SUBTRACT
#define GL_FUNC_SUBTRACT 0x800A
#endif
#ifndef GL_GENERATE_MIPMAP_HINT
#define GL_GENERATE_MIPMAP_HINT 0x8192
#endif
#ifndef GL_GEQUAL
#define GL_GEQUAL 0x0206
#endif
#ifndef GL_GREATER
#define GL_GREATER 0x0204
#endif
#ifndef GL_GREEN_BITS
#define GL_GREEN_BITS 0x0D53
#endif
#ifndef GL_HIGH_FLOAT
#define GL_HIGH_FLOAT 0x8DF2
#endif
#ifndef GL_HIGH_INT
#define GL_HIGH_INT 0x8DF5
#endif
#ifndef GL_IMPLEMENTATION_COLOR_READ_FORMAT
#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
#endif
#ifndef GL_IMPLEMENTATION_COLOR_READ_TYPE
#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
#endif
#ifndef GL_INCR
#define GL_INCR 0x1E02
#endif
#ifndef GL_INCR_WRAP
#define GL_INCR_WRAP 0x8507
#endif
#ifndef GL_INFO_LOG_LENGTH
#define GL_INFO_LOG_LENGTH 0x8B84
#endif
#ifndef GL_INT
#define GL_INT 0x1404
#endif
#ifndef GL_INT_VEC2
#define GL_INT_VEC2 0x8B53
#endif
#ifndef GL_INT_VEC3
#define GL_INT_VEC3 0x8B54
#endif
#ifndef GL_INT_VEC4
#define GL_INT_VEC4 0x8B55
#endif
#ifndef GL_INVALID_ENUM
#define GL_INVALID_ENUM 0x0500
#endif
#ifndef GL_INVALID_FRAMEBUFFER_OPERATION
#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
#endif
#ifndef GL_INVALID_OPERATION
#define GL_INVALID_OPERATION 0x0502
#endif
#ifndef GL_INVALID_VALUE
#define GL_INVALID_VALUE 0x0501
#endif
#ifndef GL_INVERT
#define GL_INVERT 0x150A
#endif
#ifndef GL_KEEP
#define GL_KEEP 0x1E00
#endif
#ifndef GL_LEQUAL
#define GL_LEQUAL 0x0203
#endif
#ifndef GL_LESS
#define GL_LESS 0x0201
#endif
#ifndef GL_LINEAR
#define GL_LINEAR 0x2601
#endif
#ifndef GL_LINEAR_MIPMAP_LINEAR
#define GL_LINEAR_MIPMAP_LINEAR 0x2703
#endif
#ifndef GL_LINEAR_MIPMAP_NEAREST
#define GL_LINEAR_MIPMAP_NEAREST 0x2701
#endif
#ifndef GL_LINE_LOOP
#define GL_LINE_LOOP 0x0002
#endif
#ifndef GL_LINES
#define GL_LINES 0x0001
#endif
#ifndef GL_LINE_STRIP
#define GL_LINE_STRIP 0x0003
#endif
#ifndef GL_LINE_WIDTH
#define GL_LINE_WIDTH 0x0B21
#endif
#ifndef GL_LINK_STATUS
#define GL_LINK_STATUS 0x8B82
#endif
#ifndef GL_LOW_FLOAT
#define GL_LOW_FLOAT 0x8DF0
#endif
#ifndef GL_LOW_INT
#define GL_LOW_INT 0x8DF3
#endif
#ifndef GL_LUMINANCE
#define GL_LUMINANCE 0x1909
#endif
#ifndef GL_LUMINANCE_ALPHA
#define GL_LUMINANCE_ALPHA 0x190A
#endif
#ifndef GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
#endif
#ifndef GL_MAX_CUBE_MAP_TEXTURE_SIZE
#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
#endif
#ifndef GL_MAX_FRAGMENT_UNIFORM_VECTORS
#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
#endif
#ifndef GL_MAX_RENDERBUFFER_SIZE
#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
#endif
#ifndef GL_MAX_TEXTURE_IMAGE_UNITS
#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
#endif
#ifndef GL_MAX_TEXTURE_SIZE
#define GL_MAX_TEXTURE_SIZE 0x0D33
#endif
#ifndef GL_MAX_VARYING_VECTORS
#define GL_MAX_VARYING_VECTORS 0x8DFC
#endif
#ifndef GL_MAX_VERTEX_ATTRIBS
#define GL_MAX_VERTEX_ATTRIBS 0x8869
#endif
#ifndef GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
#endif
#ifndef GL_MAX_VERTEX_UNIFORM_VECTORS
#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
#endif
#ifndef GL_MAX_VIEWPORT_DIMS
#define GL_MAX_VIEWPORT_DIMS 0x0D3A
#endif
#ifndef GL_MEDIUM_FLOAT
#define GL_MEDIUM_FLOAT 0x8DF1
#endif
#ifndef GL_MEDIUM_INT
#define GL_MEDIUM_INT 0x8DF4
#endif
#ifndef GL_MIRRORED_REPEAT
#define GL_MIRRORED_REPEAT 0x8370
#endif
#ifndef GL_NEAREST
#define GL_NEAREST 0x2600
#endif
#ifndef GL_NEAREST_MIPMAP_LINEAR
#define GL_NEAREST_MIPMAP_LINEAR 0x2702
#endif
#ifndef GL_NEAREST_MIPMAP_NEAREST
#define GL_NEAREST_MIPMAP_NEAREST 0x2700
#endif
#ifndef GL_NEVER
#define GL_NEVER 0x0200
#endif
#ifndef GL_NICEST
#define GL_NICEST 0x1102
#endif
#ifndef GL_NO_ERROR
#define GL_NO_ERROR 0
#endif
#ifndef GL_NONE
#define GL_NONE 0
#endif
#ifndef GL_NOTEQUAL
#define GL_NOTEQUAL 0x0205
#endif
#ifndef GL_NUM_COMPRESSED_TEXTURE_FORMATS
#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
#endif
#ifndef GL_NUM_SHADER_BINARY_FORMATS
#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
#endif
#ifndef GL_ONE
#define GL_ONE 1
#endif
#ifndef GL_ONE_MINUS_CONSTANT_ALPHA
#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
#endif
#ifndef GL_ONE_MINUS_CONSTANT_COLOR
#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
#endif
#ifndef GL_ONE_MINUS_DST_ALPHA
#define GL_ONE_MINUS_DST_ALPHA 0x0305
#endif
#ifndef GL_ONE_MINUS_DST_COLOR
#define GL_ONE_MINUS_DST_COLOR 0x0307
#endif
#ifndef GL_ONE_MINUS_SRC_ALPHA
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
#endif
#ifndef GL_ONE_MINUS_SRC_COLOR
#define GL_ONE_MINUS_SRC_COLOR 0x0301
#endif
#ifndef GL_OUT_OF_MEMORY
#define GL_OUT_OF_MEMORY 0x0505
#endif
#ifndef GL_PACK_ALIGNMENT
#define GL_PACK_ALIGNMENT 0x0D05
#endif
#ifndef GL_POINTS
#define GL_POINTS 0x0000
#endif
#ifndef GL_POLYGON_OFFSET_FACTOR
#define GL_POLYGON_OFFSET_FACTOR 0x8038
#endif
#ifndef GL_POLYGON_OFFSET_FILL
#define GL_POLYGON_OFFSET_FILL 0x8037
#endif
#ifndef GL_POLYGON_OFFSET_UNITS
#define GL_POLYGON_OFFSET_UNITS 0x2A00
#endif
#ifndef GL_RED_BITS
#define GL_RED_BITS 0x0D52
#endif
#ifndef GL_RENDERBUFFER
#define GL_RENDERBUFFER 0x8D41
#endif
#ifndef GL_RENDERBUFFER_ALPHA_SIZE
#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
#endif
#ifndef GL_RENDERBUFFER_BINDING
#define GL_RENDERBUFFER_BINDING 0x8CA7
#endif
#ifndef GL_RENDERBUFFER_BLUE_SIZE
#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
#endif
#ifndef GL_RENDERBUFFER_DEPTH_SIZE
#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
#endif
#ifndef GL_RENDERBUFFER_GREEN_SIZE
#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
#endif
#ifndef GL_RENDERBUFFER_HEIGHT
#define GL_RENDERBUFFER_HEIGHT 0x8D43
#endif
#ifndef GL_RENDERBUFFER_INTERNAL_FORMAT
#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
#endif
#ifndef GL_RENDERBUFFER_RED_SIZE
#define GL_RENDERBUFFER_RED_SIZE 0x8D50
#endif
#ifndef GL_RENDERBUFFER_STENCIL_SIZE
#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
#endif
#ifndef GL_RENDERBUFFER_WIDTH
#define GL_RENDERBUFFER_WIDTH 0x8D42
#endif
#ifndef GL_RENDERER
#define GL_RENDERER 0x1F01
#endif
#ifndef GL_REPEAT
#define GL_REPEAT 0x2901
#endif
#ifndef GL_REPLACE
#define GL_REPLACE 0x1E01
#endif
#ifndef GL_RGB
#define GL_RGB 0x1907
#endif
#ifndef GL_RGB565
#define GL_RGB565 0x8D62
#endif
#ifndef GL_RGB5_A1
#define GL_RGB5_A1 0x8057
#endif
#ifndef GL_RGBA
#define GL_RGBA 0x1908
#endif
#ifndef GL_RGBA4
#define GL_RGBA4 0x8056
#endif
#ifndef GL_BGRA
#define GL_BGRA 0x80E1
#endif
#ifndef GL_SAMPLE_ALPHA_TO_COVERAGE
#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
#endif
#ifndef GL_SAMPLE_BUFFERS
#define GL_SAMPLE_BUFFERS 0x80A8
#endif
#ifndef GL_SAMPLE_COVERAGE
#define GL_SAMPLE_COVERAGE 0x80A0
#endif
#ifndef GL_SAMPLE_COVERAGE_INVERT
#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
#endif
#ifndef GL_SAMPLE_COVERAGE_VALUE
#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
#endif
#ifndef GL_SAMPLER_2D
#define GL_SAMPLER_2D 0x8B5E
#endif
#ifndef GL_SAMPLER_CUBE
#define GL_SAMPLER_CUBE 0x8B60
#endif
#ifndef GL_SAMPLES
#define GL_SAMPLES 0x80A9
#endif
#ifndef GL_SCISSOR_BOX
#define GL_SCISSOR_BOX 0x0C10
#endif
#ifndef GL_SCISSOR_TEST
#define GL_SCISSOR_TEST 0x0C11
#endif
#ifndef GL_SHADER_BINARY_FORMATS
#define GL_SHADER_BINARY_FORMATS 0x8DF8
#endif
#ifndef GL_SHADER_COMPILER
#define GL_SHADER_COMPILER 0x8DFA
#endif
#ifndef GL_SHADER_SOURCE_LENGTH
#define GL_SHADER_SOURCE_LENGTH 0x8B88
#endif
#ifndef GL_SHADER_TYPE
#define GL_SHADER_TYPE 0x8B4F
#endif
#ifndef GL_SHADING_LANGUAGE_VERSION
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
#endif
#ifndef GL_SHORT
#define GL_SHORT 0x1402
#endif
#ifndef GL_SRC_ALPHA
#define GL_SRC_ALPHA 0x0302
#endif
#ifndef GL_SRC_ALPHA_SATURATE
#define GL_SRC_ALPHA_SATURATE 0x0308
#endif
#ifndef GL_SRC_COLOR
#define GL_SRC_COLOR 0x0300
#endif
#ifndef GL_STATIC_DRAW
#define GL_STATIC_DRAW 0x88E4
#endif
#ifndef GL_STENCIL_ATTACHMENT
#define GL_STENCIL_ATTACHMENT 0x8D20
#endif
#ifndef GL_STENCIL_BACK_FAIL
#define GL_STENCIL_BACK_FAIL 0x8801
#endif
#ifndef GL_STENCIL_BACK_FUNC
#define GL_STENCIL_BACK_FUNC 0x8800
#endif
#ifndef GL_STENCIL_BACK_PASS_DEPTH_FAIL
#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
#endif
#ifndef GL_STENCIL_BACK_PASS_DEPTH_PASS
#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
#endif
#ifndef GL_STENCIL_BACK_REF
#define GL_STENCIL_BACK_REF 0x8CA3
#endif
#ifndef GL_STENCIL_BACK_VALUE_MASK
#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
#endif
#ifndef GL_STENCIL_BACK_WRITEMASK
#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
#endif
#ifndef GL_STENCIL_BITS
#define GL_STENCIL_BITS 0x0D57
#endif
#ifndef GL_STENCIL_BUFFER_BIT
#define GL_STENCIL_BUFFER_BIT 0x00000400
#endif
#ifndef GL_STENCIL_CLEAR_VALUE
#define GL_STENCIL_CLEAR_VALUE 0x0B91
#endif
#ifndef GL_STENCIL_FAIL
#define GL_STENCIL_FAIL 0x0B94
#endif
#ifndef GL_STENCIL_FUNC
#define GL_STENCIL_FUNC 0x0B92
#endif
#ifndef GL_STENCIL_INDEX
#define GL_STENCIL_INDEX 0x1901
#endif
#ifndef GL_STENCIL_INDEX8
#define GL_STENCIL_INDEX8 0x8D48
#endif
#ifndef GL_STENCIL_PASS_DEPTH_FAIL
#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
#endif
#ifndef GL_STENCIL_PASS_DEPTH_PASS
#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
#endif
#ifndef GL_STENCIL_REF
#define GL_STENCIL_REF 0x0B97
#endif
#ifndef GL_STENCIL_TEST
#define GL_STENCIL_TEST 0x0B90
#endif
#ifndef GL_STENCIL_VALUE_MASK
#define GL_STENCIL_VALUE_MASK 0x0B93
#endif
#ifndef GL_STENCIL_WRITEMASK
#define GL_STENCIL_WRITEMASK 0x0B98
#endif
#ifndef GL_STREAM_DRAW
#define GL_STREAM_DRAW 0x88E0
#endif
#ifndef GL_SUBPIXEL_BITS
#define GL_SUBPIXEL_BITS 0x0D50
#endif
#ifndef GL_TEXTURE0
#define GL_TEXTURE0 0x84C0
#endif
#ifndef GL_TEXTURE
#define GL_TEXTURE 0x1702
#endif
#ifndef GL_TEXTURE10
#define GL_TEXTURE10 0x84CA
#endif
#ifndef GL_TEXTURE1
#define GL_TEXTURE1 0x84C1
#endif
#ifndef GL_TEXTURE11
#define GL_TEXTURE11 0x84CB
#endif
#ifndef GL_TEXTURE12
#define GL_TEXTURE12 0x84CC
#endif
#ifndef GL_TEXTURE13
#define GL_TEXTURE13 0x84CD
#endif
#ifndef GL_TEXTURE14
#define GL_TEXTURE14 0x84CE
#endif
#ifndef GL_TEXTURE15
#define GL_TEXTURE15 0x84CF
#endif
#ifndef GL_TEXTURE16
#define GL_TEXTURE16 0x84D0
#endif
#ifndef GL_TEXTURE17
#define GL_TEXTURE17 0x84D1
#endif
#ifndef GL_TEXTURE18
#define GL_TEXTURE18 0x84D2
#endif
#ifndef GL_TEXTURE19
#define GL_TEXTURE19 0x84D3
#endif
#ifndef GL_TEXTURE20
#define GL_TEXTURE20 0x84D4
#endif
#ifndef GL_TEXTURE2
#define GL_TEXTURE2 0x84C2
#endif
#ifndef GL_TEXTURE21
#define GL_TEXTURE21 0x84D5
#endif
#ifndef GL_TEXTURE22
#define GL_TEXTURE22 0x84D6
#endif
#ifndef GL_TEXTURE23
#define GL_TEXTURE23 0x84D7
#endif
#ifndef GL_TEXTURE24
#define GL_TEXTURE24 0x84D8
#endif
#ifndef GL_TEXTURE25
#define GL_TEXTURE25 0x84D9
#endif
#ifndef GL_TEXTURE26
#define GL_TEXTURE26 0x84DA
#endif
#ifndef GL_TEXTURE27
#define GL_TEXTURE27 0x84DB
#endif
#ifndef GL_TEXTURE28
#define GL_TEXTURE28 0x84DC
#endif
#ifndef GL_TEXTURE29
#define GL_TEXTURE29 0x84DD
#endif
#ifndef GL_TEXTURE_2D
#define GL_TEXTURE_2D 0x0DE1
#endif
#ifndef GL_TEXTURE30
#define GL_TEXTURE30 0x84DE
#endif
#ifndef GL_TEXTURE3
#define GL_TEXTURE3 0x84C3
#endif
#ifndef GL_TEXTURE31
#define GL_TEXTURE31 0x84DF
#endif
#ifndef GL_TEXTURE4
#define GL_TEXTURE4 0x84C4
#endif
#ifndef GL_TEXTURE5
#define GL_TEXTURE5 0x84C5
#endif
#ifndef GL_TEXTURE6
#define GL_TEXTURE6 0x84C6
#endif
#ifndef GL_TEXTURE7
#define GL_TEXTURE7 0x84C7
#endif
#ifndef GL_TEXTURE8
#define GL_TEXTURE8 0x84C8
#endif
#ifndef GL_TEXTURE9
#define GL_TEXTURE9 0x84C9
#endif
#ifndef GL_TEXTURE_BINDING_2D
#define GL_TEXTURE_BINDING_2D 0x8069
#endif
#ifndef GL_TEXTURE_BINDING_CUBE_MAP
#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
#endif
#ifndef GL_TEXTURE_CUBE_MAP
#define GL_TEXTURE_CUBE_MAP 0x8513
#endif
#ifndef GL_TEXTURE_CUBE_MAP_NEGATIVE_X
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
#endif
#ifndef GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
#endif
#ifndef GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
#endif
#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_X
#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
#endif
#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_Y
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
#endif
#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_Z
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
#endif
#ifndef GL_TEXTURE_MAG_FILTER
#define GL_TEXTURE_MAG_FILTER 0x2800
#endif
#ifndef GL_TEXTURE_MIN_FILTER
#define GL_TEXTURE_MIN_FILTER 0x2801
#endif
#ifndef GL_TEXTURE_WRAP_S
#define GL_TEXTURE_WRAP_S 0x2802
#endif
#ifndef GL_TEXTURE_WRAP_T
#define GL_TEXTURE_WRAP_T 0x2803
#endif
#ifndef GL_TRIANGLE_FAN
#define GL_TRIANGLE_FAN 0x0006
#endif
#ifndef GL_TRIANGLES
#define GL_TRIANGLES 0x0004
#endif
#ifndef GL_TRIANGLE_STRIP
#define GL_TRIANGLE_STRIP 0x0005
#endif
#ifndef GL_TRUE
#define GL_TRUE 1
#endif
#ifndef GL_UNPACK_ALIGNMENT
#define GL_UNPACK_ALIGNMENT 0x0CF5
#endif
#ifndef GL_UNSIGNED_BYTE
#define GL_UNSIGNED_BYTE 0x1401
#endif
#ifndef GL_UNSIGNED_INT
#define GL_UNSIGNED_INT 0x1405
#endif
#ifndef GL_UNSIGNED_SHORT
#define GL_UNSIGNED_SHORT 0x1403
#endif
#ifndef GL_UNSIGNED_SHORT_4_4_4_4
#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
#endif
#ifndef GL_UNSIGNED_SHORT_5_5_5_1
#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
#endif
#ifndef GL_UNSIGNED_SHORT_5_6_5
#define GL_UNSIGNED_SHORT_5_6_5 0x8363
#endif
#ifndef GL_VALIDATE_STATUS
#define GL_VALIDATE_STATUS 0x8B83
#endif
#ifndef GL_VENDOR
#define GL_VENDOR 0x1F00
#endif
#ifndef GL_VERSION
#define GL_VERSION 0x1F02
#endif
#ifndef GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
#endif
#ifndef GL_VERTEX_ATTRIB_ARRAY_ENABLED
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
#endif
#ifndef GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
#endif
#ifndef GL_VERTEX_ATTRIB_ARRAY_POINTER
#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
#endif
#ifndef GL_VERTEX_ATTRIB_ARRAY_SIZE
#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
#endif
#ifndef GL_VERTEX_ATTRIB_ARRAY_STRIDE
#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
#endif
#ifndef GL_VERTEX_ATTRIB_ARRAY_TYPE
#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
#endif
#ifndef GL_VERTEX_SHADER
#define GL_VERTEX_SHADER 0x8B31
#endif
#ifndef GL_VIEWPORT
#define GL_VIEWPORT 0x0BA2
#endif
#ifndef GL_ZERO
#define GL_ZERO 0
#endif

QT_END_NAMESPACE

#endif


text:
# Disallow Shadowing of Variables Inside of catch (no-catch-shadow)

In IE 8 and earlier, the catch clause parameter can overwrite the value of a variable in the outer scope, if that variable has the same name as the catch clause parameter.

```js
var err = "x";

try {
    throw "problem";
} catch (err) {

}

console.log(err)    // err is 'problem', not 'x'
```

## Rule Details

This rule is aimed at preventing unexpected behavior in your program that may arise from a bug in IE 8 and earlier, in which the catch clause parameter can leak into outer scopes. This rule will warn whenever it encounters a catch clause parameter that has the same name as a variable in an outer scope.

Examples of **incorrect** code for this rule:

```js
/*eslint no-catch-shadow: "error"*/

var err = "x";

try {
    throw "problem";
} catch (err) {

}

function err() {
    // ...
};

try {
    throw "problem";
} catch (err) {

}
```

Examples of **correct** code for this rule:

```js
/*eslint no-catch-shadow: "error"*/

var err = "x";

try {
    throw "problem";
} catch (e) {

}

function err() {
    // ...
};

try {
    throw "problem";
} catch (e) {

}
```

## When Not To Use It

If you do not need to support IE 8 and earlier, you should turn this rule off.

redpajama_set_name: RedPajamaGithub


text:
namespace omaha {

namespace {

const TCHAR* const kMsiSuppressAllRebootsCmdLine = _T("REBOOT=ReallySuppress");

#ifdef _DEBUG
HRESULT VerifyCOMLocalServerRegistration(bool is_machine) {
  // Validate the following:
  // * LocalServer32 under CLSID_OnDemandMachineAppsClass or
  //   CLSID_OnDemandUserAppsClass should be ...Google\Update\GoogleUpdate.exe.
  // * InProcServer32 under CLSID of IID_IGoogleUpdate should be
  //   ...Google\Update\{version}\goopdate.dll.
  // * ProxyStubClsid32 under IGoogleUpdate interface should be the CLSID of the
  //   proxy, which is IID_IGoogleUpdate.

  CString base_clsid_key(goopdate_utils::GetHKRoot());
  base_clsid_key += _T("\\Software\\Classes\\CLSID\\");
  CString ondemand_clsid_key(base_clsid_key);
  ondemand_clsid_key += GuidToString(is_machine ?
                                     __uuidof(OnDemandMachineAppsClass) :
                                     __uuidof(OnDemandUserAppsClass));
  CString local_server_key(ondemand_clsid_key + _T("\\LocalServer32"));
  CString installed_server;
  ASSERT1(SUCCEEDED(RegKey::GetValue(local_server_key,
                                     NULL,
                                     &installed_server)));
  ASSERT1(!installed_server.IsEmpty());

  CString expected_server(app_util::GetModulePath(NULL));
  EnclosePath(&expected_server);
  ASSERT1(!expected_server.IsEmpty());
  SETUP_LOG(L3, (_T("[installed_server=%s][expected_server=%s]"),
                 installed_server, expected_server));
  ASSERT1(installed_server == expected_server);

  const GUID proxy_clsid = PROXY_CLSID_IS;
  CString ondemand_proxy_clsid_key(base_clsid_key);
  ondemand_proxy_clsid_key += GuidToString(proxy_clsid);
  CString inproc_server_key(ondemand_proxy_clsid_key + _T("\\InProcServer32"));
  ASSERT1(SUCCEEDED(RegKey::GetValue(inproc_server_key,
                                     NULL,
                                     &installed_server)));
  ASSERT1(!installed_server.IsEmpty());
  expected_server = app_util::GetCurrentModulePath();
  ASSERT1(!expected_server.IsEmpty());
  SETUP_LOG(L3, (_T("[installed proxy=%s][expected proxy=%s]"),
                 installed_server, expected_server));
  ASSERT1(installed_server == expected_server);

  CString igoogleupdate_interface_key(goopdate_utils::GetHKRoot());
  igoogleupdate_interface_key += _T("\\Software\\Classes\\Interface\\");
  igoogleupdate_interface_key += GuidToString(__uuidof(IGoogleUpdate));
  igoogleupdate_interface_key += _T("\\ProxyStubClsid32");
  CString proxy_interface_value;
  ASSERT1(SUCCEEDED(RegKey::GetValue(igoogleupdate_interface_key,
                                     NULL,
                                     &proxy_interface_value)));
  ASSERT1(!proxy_interface_value.IsEmpty());
  ASSERT1(proxy_interface_value == GuidToString(proxy_clsid));

  return S_OK;
}
#endif

}  // namespace

SetupGoogleUpdate::SetupGoogleUpdate(bool is_machine,
                                     const CommandLineArgs* args)
    : is_machine_(is_machine),
#ifdef _DEBUG
      have_called_uninstall_previous_versions_(false),
#endif
      args_(args) {
  this_version_ = GetVersionString();
}

SetupGoogleUpdate::~SetupGoogleUpdate() {
  SETUP_LOG(L2, (_T("[SetupGoogleUpdate::~SetupGoogleUpdate]")));
}

// TODO(omaha): Add a VerifyInstall() method that can be called by /handoff
// instances to verify the installation and call FinishInstall() if it fails.

// Assumes the caller is ensuring this is the only running instance of setup.
// The original process holds the lock while it waits for this one to complete.
HRESULT SetupGoogleUpdate::FinishInstall() {
  SETUP_LOG(L2, (_T("[SetupGoogleUpdate::FinishInstall]")));

  HRESULT hr = InstallRegistryValues();
  if (FAILED(hr)) {
    SETUP_LOG(LE, (_T("[InstallRegistryValues failed][0x%08x]"), hr));
    return hr;
  }

  hr = InstallLaunchMechanisms();
  if (FAILED(hr)) {
    SETUP_LOG(LE, (_T("[InstallLaunchMechanisms failed][0x%08x]"), hr));
    return hr;
  }

  hr = InstallMsiHelper();
  if (FAILED(hr)) {
    SETUP_LOG(L1, (_T("[InstallMsiHelper failed][0x%08x]"), hr));
    // TODO(omaha): Retry on ERROR_INSTALL_ALREADY_RUNNING like InstallManager
    // if we move helper MSI installation after app installation.
    ASSERT1(HRESULT_FROM_WIN32(ERROR_INSTALL_SERVICE_FAILURE) == hr ||
            HRESULT_FROM_WIN32(ERROR_INSTALL_ALREADY_RUNNING) == hr);
  }

  HRESULT hr_register_com_server(RegisterOrUnregisterCOMLocalServer(true));
  ASSERT1(SUCCEEDED(hr_register_com_server));
  if (FAILED(hr_register_com_server)) {
    OPT_LOG(L3, (_T("[RegisterOrUnregisterCOMLocalServer failed][0x%x]"),
                 hr_register_com_server));
    Ping ping;
    VERIFY1(SUCCEEDED(ping_utils::SendGoopdatePing(
                                      is_machine_,
                                      args_->extra,
                                      args_->install_source,
                                      PingEvent::EVENT_SETUP_COM_SERVER_FAILURE,
                                      hr_register_com_server,
                                      0,
                                      NULL,
                                      &ping)));
  }

  ASSERT1(SUCCEEDED(VerifyCOMLocalServerRegistration(is_machine_)));

  // We would prefer to uninstall previous versions last, but the web plugin
  // requires that the old plugin is uninstalled before installing the new one.
  VERIFY1(SUCCEEDED(UninstallPreviousVersions()));
  VERIFY1(SUCCEEDED(InstallOptionalComponents()));

  // Writing this value indicates that this Omaha version was successfully
  // installed.
  CString reg_update = ConfigManager::Instance()->registry_update(is_machine_);
  hr = RegKey::SetValue(reg_update, kRegValueInstalledVersion, this_version_);
  if (FAILED(hr)) {
    return hr;
  }

  // Delete the "LastChecked" registry value after a successful install or
  // update so that Omaha checks for updates soon after the install. This
  // helps detecting a heart beat from the new version sooner as well as
  // avoiding deferring application updates for too long in the case where both
  // Omaha and application updates are available.
  RegKey::DeleteValue(reg_update, kRegValueLastChecked);

  return S_OK;
}

HRESULT SetupGoogleUpdate::InstallRegistryValues() {
  OPT_LOG(L3, (_T("[SetupGoogleUpdate::InstallRegistryValues]")));

  const ConfigManager* cm = ConfigManager::Instance();
  const TCHAR* keys[] = { cm->registry_google(is_machine_),
                          cm->registry_update(is_machine_),
                          cm->registry_client_state(is_machine_),
                          cm->registry_clients(is_machine_),
                          cm->registry_clients_goopdate(is_machine_),
                          cm->registry_client_state_goopdate(is_machine_),
                        };

  HRESULT hr = RegKey::CreateKeys(keys, arraysize(keys));
  if (FAILED(hr)) {
    OPT_LOG(LE, (_T("[Failed to create reg keys][0x%08x]"), hr));
    return hr;
  }

  if (is_machine_) {
    hr = CreateClientStateMedium();
    if (FAILED(hr)) {
      SETUP_LOG(L3, (_T("[CreateClientStateMedium failed][0x%08x]"), hr));
      return hr;
    }
  }

  CString shell_path = goopdate_utils::BuildGoogleUpdateExePath(is_machine_);
  if (shell_path.IsEmpty() || !File::Exists(shell_path)) {
    SETUP_LOG(LE, (_T("[Failed to get valid shell path]")));
    return E_FAIL;
  }
  hr = RegKey::SetValue(cm->registry_update(is_machine_),
                        kRegValueInstalledPath,
                        shell_path);
  if (FAILED(hr)) {
    SETUP_LOG(LE, (_T("[Failed to write shell path][0x%08x]"), hr));
    return hr;
  }

  // Set all the information for this instance correctly in the registry.
  const CString goopdate_state_key_name =
      cm->registry_client_state_goopdate(is_machine_);

  // IID and branding are optional, so ignore errors.
  VERIFY1(SUCCEEDED(SetInstallationId()));
  VERIFY1(SUCCEEDED(goopdate_utils::SetGoogleUpdateBranding(
      goopdate_state_key_name,
      args_->extra.brand_code,
      args_->extra.client_id)));

  // Set pv in ClientState for consistency. Optional, so ignore errors.
  ASSERT1(!this_version_.IsEmpty());
  VERIFY1(SUCCEEDED(RegKey::SetValue(goopdate_state_key_name,
                                     kRegValueProductVersion,
                                     this_version_)));

  return S_OK;
}

// Creates the ClientStateMedium key and adds ACLs that allows authenticated
// users to read and write values in its subkeys.
// Since this key is not as secure as other keys, the supported values must be
// limited and the use of them must be carefully designed.
HRESULT SetupGoogleUpdate::CreateClientStateMedium() {
  ASSERT1(is_machine_);

  // Authenticated non-admins may read, write, and create values.
  const ACCESS_MASK kNonAdminAccessMask = KEY_READ | KEY_SET_VALUE;
  // The override privileges apply to all subkeys and values but not to the
  // ClientStateMedium key itself.
  const uint8 kAceFlags =
      CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE;

  const CString key_full_name =
      ConfigManager::Instance()->machine_registry_client_state_medium();
  HRESULT hr = RegKey::CreateKey(key_full_name);
  if (FAILED(hr)) {
    SETUP_LOG(LE, (_T("[Create ClientStateMedium failed][0x%08x]"), hr));
    return hr;
  }

  // GetNamedSecurityInfo requires the key name start with "MACHINE".
  // TODO(omaha): Replace AddAllowedAce or add an override that takes a handle
  // instead of a name to eliminate this issue.
  CString compatible_key_name = key_full_name;
  VERIFY1(1 == compatible_key_name.Replace(MACHINE_KEY_NAME, _T("MACHINE")));

  hr = AddAllowedAce(compatible_key_name,
                     SE_REGISTRY_KEY,
                     Sids::Interactive(),
                     kNonAdminAccessMask,
                     kAceFlags);
  if (FAILED(hr)) {
    SETUP_LOG(LE, (_T("[AddAllowedAce failed][%s][0x%08x]"),
                   key_full_name, hr));
    return hr;
  }

  return S_OK;
}

// Overwrites any existing IID for Omaha if a new one is specified.
HRESULT SetupGoogleUpdate::SetInstallationId() {
  SETUP_LOG(L3, (_T("[SetupGoogleUpdate::SetInstallationId]")));

  if (GUID_NULL != args_->extra.installation_id) {
    CString goopdate_state_key_name =
        ConfigManager::Instance()->registry_client_state_goopdate(is_machine_);
    return RegKey::SetValue(goopdate_state_key_name,
                            kRegValueInstallationId,
                            GuidToString(args_->extra.installation_id));
  }

  return S_OK;
}

HRESULT SetupGoogleUpdate::InstallLaunchMechanisms() {
  SETUP_LOG(L3, (_T("[SetupGoogleUpdate::InstallLaunchMechanisms]")));
  if (is_machine_) {
    HRESULT hr = InstallMachineLaunchMechanisms();
    if (FAILED(hr)) {
      SETUP_LOG(LE, (_T("[InstallMachineLaunchMechanisms fail][0x%08x]"), hr));
      return hr;
    }
  } else {
    HRESULT hr = InstallUserLaunchMechanisms();
    if (FAILED(hr)) {
      SETUP_LOG(LE, (_T("[InstallUserLaunchMechanisms failed][0x%08x]"), hr));
      return hr;
    }
  }

  return S_OK;
}

void SetupGoogleUpdate::UninstallLaunchMechanisms() {
  SETUP_LOG(L3, (_T("[SetupGoogleUpdate::UninstallLaunchMechanisms]")));
  if (is_machine_) {
    VERIFY1(SUCCEEDED(SetupService::UninstallService()));
  } else {
    // We only need to do this in case of the user goopdate, as
    // there is no machine Run at startup installation.
    VERIFY1(SUCCEEDED(ConfigureUserRunAtStartup(false)));  // delete entry
  }

  VERIFY1(SUCCEEDED(goopdate_utils::UninstallGoopdateTasks(is_machine_)));
}

HRESULT SetupGoogleUpdate::InstallScheduledTask() {
  CString exe_path = goopdate_utils::BuildGoogleUpdateExePath(is_machine_);

  HighresTimer metrics_timer;
  const ULONGLONG install_task_start_ms = metrics_timer.GetElapsedMs();

  HRESULT hr = goopdate_utils::InstallGoopdateTasks(exe_path, is_machine_);

  if (SUCCEEDED(hr)) {
    const ULONGLONG install_task_end_ms = metrics_timer.GetElapsedMs();
    ASSERT1(install_task_end_ms >= install_task_start_ms);
    metric_setup_install_task_ms.AddSample(
        install_task_end_ms - install_task_start_ms);
    ++metric_setup_install_task_succeeded;
  } else {
    OPT_LOG(LEVEL_ERROR, (_T("[Install task failed][0x%08x]"), hr));
    metric_setup_install_task_error = hr;
  }

  return hr;
}

// Assumes the any existing service instance has been stopped
// TODO(omaha): Provide service_hr and task_hr failures in a ping.
// They are no longer being provided in the URL.
HRESULT SetupGoogleUpdate::InstallMachineLaunchMechanisms() {
  SETUP_LOG(L3, (_T("[SetupGoogleUpdate::InstallMachineLaunchMechanisms]")));
  ++metric_setup_install_service_task_total;

  // Install the service and scheduled task. Failing to install both will
  // fail setup.
  OPT_LOG(L1, (_T("[Installing service]")));
  HighresTimer metrics_timer;

  HRESULT service_hr = SetupService::InstallService(
      goopdate_utils::BuildGoogleUpdateExePath(is_machine_));

  if (SUCCEEDED(service_hr)) {
    metric_setup_install_service_ms.AddSample(
        metrics_timer.GetElapsedMs());
    ++metric_setup_install_service_succeeded;
  } else {
    metric_setup_install_service_failed_ms.AddSample(
        metrics_timer.GetElapsedMs());
    OPT_LOG(LEVEL_ERROR, (_T("[Install service failed][0x%08x]"), service_hr));
    metric_setup_install_service_error = service_hr;
  }

  HRESULT task_hr = InstallScheduledTask();

  if (FAILED(service_hr) && FAILED(task_hr)) {
    ++metric_setup_install_service_and_task_failed;
    return service_hr;
  }
  if (args_->is_oem_set) {
    // OEM installs are on clean systems in a controlled environment. We expect
    // both mechanisms to install.
    if (FAILED(service_hr)) {
      return service_hr;
    }
    if (FAILED(task_hr)) {
      return task_hr;
    }
  }

  if (SUCCEEDED(service_hr) && SUCCEEDED(task_hr)) {
    ++metric_setup_install_service_and_task_succeeded;
  }

  return S_OK;
}

HRESULT SetupGoogleUpdate::InstallUserLaunchMechanisms() {
  SETUP_LOG(L3, (_T("[SetupGoogleUpdate::InstallUserLaunchMechanisms]")));

  HRESULT run_hr = ConfigureUserRunAtStartup(true);  // install
  ASSERT(SUCCEEDED(run_hr), (_T("ConfigureRunAtStartup 0x%x"), run_hr));

  HRESULT task_hr = InstallScheduledTask();
  ASSERT(SUCCEEDED(task_hr), (_T("InstallScheduledTask 0x%x"), task_hr));

  if (FAILED(run_hr) && FAILED(task_hr)) {
    // We need atleast one launch mechanism.
    return run_hr;
  }

  return S_OK;
}

// Sets a value in the Run key in the user registry to start the core.
HRESULT SetupGoogleUpdate::ConfigureUserRunAtStartup(bool install) {
  SETUP_LOG(L3, (_T("SetupGoogleUpdate::ConfigureUserRunAtStartup")));
  // Always send false argument as this method is only called for user
  // goopdate installs.
  CString core_cmd = BuildCoreProcessCommandLine();
  return ConfigureRunAtStartup(USER_KEY_NAME, kRunValueName, core_cmd, install);
}

HRESULT SetupGoogleUpdate::RegisterOrUnregisterCOMLocalServer(bool reg) {
  SETUP_LOG(L3, (_T("[SetupGoogleUpdate::RegisterOrUnregisterCOMLocalServer]")
                 _T("[%d]"), reg));
  CString google_update_path = goopdate_utils::BuildGoogleUpdateExePath(
                                   is_machine_);
  CString register_cmd;
  register_cmd.Format(_T("/%s"), reg ? _T("RegServer") : _T("UnregServer"));
  HRESULT hr = RegisterOrUnregisterExe(google_update_path, register_cmd);
  if (FAILED(hr)) {
    SETUP_LOG(LE, (_T("[RegisterOrUnregisterExe failed][0x%08x]"), hr));
    return hr;
  }
  return S_OK;
}

// Assumes that the MSI is in the current directory.
// To debug MSI failures, use the following statement:
// ::MsiEnableLog(INSTALLLOGMODE_VERBOSE, _T("C:\\msi.log"), NULL);
HRESULT SetupGoogleUpdate::InstallMsiHelper() {
  SETUP_LOG(L3, (_T("[SetupGoogleUpdate::InstallMsiHelper]")));
  if (!is_machine_) {
    return S_OK;
  }

  ++metric_setup_helper_msi_install_total;
  HighresTimer metrics_timer;

  CString msi_path(app_util::GetCurrentModuleDirectory());
  if (!::PathAppend(CStrBuf(msi_path, MAX_PATH), kHelperInstallerName)) {
    ASSERT1(false);
    return GOOPDATE_E_PATH_APPEND_FAILED;
  }

  // Setting INSTALLUILEVEL_NONE causes installation to be silent and not
  // create a restore point.
  ::MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);

  // Try a normal install.
  UINT res = ::MsiInstallProduct(msi_path, kMsiSuppressAllRebootsCmdLine);
  if (ERROR_PRODUCT_VERSION == res) {
    // The product may already be installed. Force a reinstall of everything.
    SETUP_LOG(L3, (_T("[ERROR_PRODUCT_VERSION returned - forcing reinstall]")));
    CString force_install_cmd_line;
    force_install_cmd_line.Format(_T("REINSTALL=ALL REINSTALLMODE=vamus %s"),
                                  kMsiSuppressAllRebootsCmdLine);
    res = ::MsiInstallProduct(msi_path, force_install_cmd_line);
  }

  HRESULT hr = HRESULT_FROM_WIN32(res);
  if (FAILED(hr)) {
    SETUP_LOG(L1, (_T("[MsiInstallProduct failed][0x%08x][%u]"), hr, res));
    return hr;
  }

  metric_setup_helper_msi_install_ms.AddSample(metrics_timer.GetElapsedMs());
  ++metric_setup_helper_msi_install_succeeded;
  return S_OK;
}

// The MSI is uninstalled.
// TODO(omaha): Make sure this works after deleting the MSI.
HRESULT SetupGoogleUpdate::UninstallMsiHelper() {
  SETUP_LOG(L3, (_T("[SetupGoogleUpdate::UninstallMsiHelper]")));
  if (!is_machine_) {
    return S_OK;
  }

  // Setting INSTALLUILEVEL_NONE causes installation to be silent and not
  // create a restore point.
  ::MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
  // MSDN says that eInstallState must be INSTALLSTATE_DEFAULT in order for the
  // command line to be used. Therefore, instead of using INSTALLSTATE_ABSENT
  // to uninstall, we must pass REMOVE=ALL in the command line.
  CString uninstall_cmd_line;
  uninstall_cmd_line.Format(_T("REMOVE=ALL %s"),
                            kMsiSuppressAllRebootsCmdLine);
  UINT res = ::MsiConfigureProductEx(kHelperInstallerProductGuid,
                                     INSTALLLEVEL_DEFAULT,
                                     INSTALLSTATE_DEFAULT,
                                     uninstall_cmd_line);

  // Ignore the product not currently installed result.
  if ((ERROR_SUCCESS != res) && (ERROR_UNKNOWN_PRODUCT != res)) {
    HRESULT hr = HRESULT_FROM_WIN32(res);
    if (FAILED(hr)) {
      SETUP_LOG(L1, (_T("[MsiInstallProduct failed][0x%08x][%u]"), hr, res));
      return hr;
    }
  }

  return S_OK;
}

HRESULT SetupGoogleUpdate::InstallOptionalComponents() {
  SETUP_LOG(L3, (_T("[SetupGoogleUpdate::InstallOptionalComponents]")));
  ASSERT1(have_called_uninstall_previous_versions_);
  // Failure of registration of optional components is acceptable in release
  // builds.
  HRESULT hr = S_OK;

  CString goopdate_oneclick_path =
      BuildSupportFileInstallPath(ACTIVEX_FILENAME);
  hr = RegisterDll(goopdate_oneclick_path);
  if (FAILED(hr)) {
    SETUP_LOG(L1, (_T("[Register OneClick DLL failed][0x%08x]"), hr));
  }

#if 0
  // Only install the BHO for machine installs. There is no corresponding HKCU
  // registration for BHOs.
  if (is_machine_) {
    CString goopdate_bho_proxy_path = BuildSupportFileInstallPath(BHO_FILENAME);
    hr = RegisterDll(goopdate_bho_proxy_path);
    if (FAILED(hr)) {
      SETUP_LOG(L1, (_T("[Register bho_proxy DLL failed][0x%08x]"), hr));
    }
  }
#endif

  return hr;
}

HRESULT SetupGoogleUpdate::UninstallOptionalComponents() {
  SETUP_LOG(L3, (_T("[SetupGoogleUpdate::UninstallOptionalComponents]")));
  // Unregistration. Failure is acceptable in release builds.
  HRESULT hr = S_OK;

  CString goopdate_oneclick_path =
      BuildSupportFileInstallPath(ACTIVEX_FILENAME);
  hr = UnregisterDll(goopdate_oneclick_path);
  if (FAILED(hr)) {
    SETUP_LOG(L1, (_T("[Unregister OneClick DLL failed][0x%08x]"), hr));
  }

#if 0
  if (is_machine_) {
    CString goopdate_bho_proxy_path = BuildSupportFileInstallPath(BHO_FILENAME);
    hr = UnregisterDll(goopdate_bho_proxy_path);
    if (FAILED(hr)) {
      SETUP_LOG(L1, (_T("[Unregister bho_proxy DLL failed][0x%08x]"), hr));
    }
  }
#endif

  return hr;
}

CString SetupGoogleUpdate::BuildSupportFileInstallPath(
    const CString& filename) const {
  SETUP_LOG(L3, (_T("[SetupGoogleUpdate::BuildSupportFileInstallPath][%s]"),
                 filename));
  CPath install_file_path = goopdate_utils::BuildInstallDirectory(
                                is_machine_,
                                this_version_);
  VERIFY1(install_file_path.Append(filename));

  return install_file_path;
}

CString SetupGoogleUpdate::BuildCoreProcessCommandLine() const {
  CommandLineBuilder builder(COMMANDLINE_MODE_CORE);
  CString google_update_path = goopdate_utils::BuildGoogleUpdateExePath(
                                   is_machine_);
  return builder.GetCommandLine(google_update_path);
}

HRESULT SetupGoogleUpdate::UninstallPreviousVersions() {
#ifdef _DEBUG
  have_called_uninstall_previous_versions_ = true;
#endif

  VERIFY1(SUCCEEDED(goopdate_utils::UninstallLegacyGoopdateTasks(is_machine_)));

  CString install_path(
      is_machine_ ? ConfigManager::Instance()->GetMachineGoopdateInstallDir() :
                    ConfigManager::Instance()->GetUserGoopdateInstallDir());
  SETUP_LOG(L1, (_T("[SetupGoogleUpdate::UninstallPreviousVersions][%s][%s]"),
                 install_path, this_version_));
  // An empty install_path can be disastrous as it will start deleting from the
  // current directory.
  ASSERT1(!install_path.IsEmpty());
  if (install_path.IsEmpty()) {
    return E_UNEXPECTED;
  }

  // In the Google\\Update directory, run over all files and directories.
  WIN32_FIND_DATA file_data = {0};
  CPath find_files(install_path);
  VERIFY1(find_files.Append(_T("*.*")));

  scoped_hfind find_handle(::FindFirstFile(find_files, &file_data));
  ASSERT1(find_handle);
  if (!find_handle) {
    // We should have found ".", "..", and our versioned directory.
    DWORD err = ::GetLastError();
    SETUP_LOG(LE, (L"[Subdirs not found under dir][%s][%d]", find_files, err));
    return HRESULT_FROM_WIN32(err);
  }

  BOOL found_next = TRUE;
  for (; found_next; found_next = ::FindNextFile(get(find_handle),
                                                 &file_data)) {
    CPath file_or_directory(install_path);
    VERIFY1(file_or_directory.Append(file_data.cFileName));
    if (!(file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
      // Do not delete the shell as it is used by all versions.
      if (_tcsicmp(file_data.cFileName, kGoopdateFileName)) {
        DeleteBeforeOrAfterReboot(file_or_directory);
      }
    } else if (_tcscmp(file_data.cFileName, _T("..")) &&
               _tcscmp(file_data.cFileName, _T(".")) &&
               _tcsicmp(file_data.cFileName, this_version_) &&
               (!args_->is_offline_set ||
                _tcscmp(file_data.cFileName, OFFLINE_DIR_NAME))) {
      // Unregister the previous version OneClick if it exists. Ignore
      // failures. The file is named npGoogleOneClick*.dll.
      CPath old_oneclick(file_or_directory);
      VERIFY1(old_oneclick.Append(ACTIVEX_NAME _T("*.dll")));
      WIN32_FIND_DATA old_oneclick_file_data = {0};
      scoped_hfind found_oneclick(::FindFirstFile(old_oneclick,
                                                  &old_oneclick_file_data));
      if (found_oneclick) {
        CPath old_oneclick_file(file_or_directory);
        VERIFY1(old_oneclick_file.Append(old_oneclick_file_data.cFileName));
        VERIFY1(SUCCEEDED(UnregisterDll(old_oneclick_file)));
      }

      if (is_machine_) {
        // BHO is only installed for the machine case.
        // Unregister the previous version BHO if it exists. Ignore failures.
        CPath old_bho_dll(file_or_directory);
        VERIFY1(old_bho_dll.Append(BHO_FILENAME));
        if (File::Exists(old_bho_dll)) {
          if (FAILED(UnregisterDll(old_bho_dll))) {
            SETUP_LOG(LW, (L"[UnregisterDll() failed][%s]", old_bho_dll));
          }
        }
      }
      // Delete entire sub-directory.
      DeleteBeforeOrAfterReboot(file_or_directory);
    }
  }

  if (!found_next) {
    DWORD err = ::GetLastError();
    if (ERROR_NO_MORE_FILES != err) {
      SETUP_LOG(LE, (L"[::FindNextFile() failed][%d]", err));
      return HRESULT_FROM_WIN32(err);
    }
  }

  // Need to clean up old lang key for Goopdate.  Don't care about failure.
  CString goopdate_client_key =
      ConfigManager::Instance()->registry_clients_goopdate(is_machine_);
  RegKey::DeleteValue(goopdate_client_key, kRegValueLanguage);

  // Clean up existing machine ID and user ID since they are no longer used.
  // Ignore failures as they may not be present and we may not have permission
  // to HKLM.
  const TCHAR* const kRegValueMachineId = _T("mi");
  const TCHAR* const kRegValueUserId = _T("ui");
  RegKey::DeleteValue(ConfigManager::Instance()->machine_registry_update(),
                      kRegValueMachineId);
  RegKey::DeleteValue(
      ConfigManager::Instance()->registry_update(is_machine_),
      kRegValueUserId);

  return S_OK;
}

void SetupGoogleUpdate::Uninstall() {
  OPT_LOG(L1, (_T("[SetupGoogleUpdate::Uninstall]")));

  HRESULT hr = UninstallOptionalComponents();
  if (FAILED(hr)) {
    SETUP_LOG(LW, (_T("[UninstallOptionalComponents failed][0x%08x]"), hr));
    ASSERT1(HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND) == hr);
  }

  // TODO(omaha): Some of the checks assume that The uninstall is being
  // executed from the installed path. This is not the case when /install is
  // uninstalling and will also not be the case when Setup is merged into one
  // process.
  if (goopdate_utils::IsRunningFromOfficialGoopdateDir(is_machine_)) {
    ASSERT1(SUCCEEDED(VerifyCOMLocalServerRegistration(is_machine_)));
  }
  hr = RegisterOrUnregisterCOMLocalServer(false);
  if (FAILED(hr)) {
    SETUP_LOG(LW,
              (_T("[RegisterOrUnregisterCOMLocalServer failed][0x%08x]"), hr));
    ASSERT1(GOOGLEUPDATE_E_DLL_NOT_FOUND == hr ||
            HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr);
  }

  hr = UninstallMsiHelper();
  if (FAILED(hr)) {
    SETUP_LOG(L1, (_T("[UninstallMsiHelper failed][0x%08x]"), hr));
    ASSERT1(HRESULT_FROM_WIN32(ERROR_INSTALL_SERVICE_FAILURE) == hr);
  }

  UninstallLaunchMechanisms();

  // Remove everything under top level Google Update registry key.
  hr = DeleteRegistryKeys();
  ASSERT1(SUCCEEDED(hr) || HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr);
}

// Also deletes the main Google Update key if there is nothing in it.
HRESULT SetupGoogleUpdate::DeleteRegistryKeys() {
  OPT_LOG(L3, (_T("[SetupGoogleUpdate::DeleteRegistryKeys]")));

  CString root_key = ConfigManager::Instance()->registry_update(is_machine_);
  ASSERT1(!root_key.IsEmpty());

  RegKey root;
  HRESULT hr = root.Open(root_key);
  if (FAILED(hr)) {
    return hr;
  }

  std::vector<CString> sub_keys;
  size_t num_keys = root.GetSubkeyCount();
  for (size_t i = 0; i < num_keys; ++i) {
    CString sub_key_name;
    hr = root.GetSubkeyNameAt(i, &sub_key_name);
    ASSERT1(hr == S_OK);
    if (SUCCEEDED(hr)) {
      sub_keys.push_back(sub_key_name);
    }
  }

  ASSERT1(num_keys == sub_keys.size());
  // Delete all the sub keys of the root key.
  for (size_t i = 0; i < num_keys; ++i) {
    VERIFY1(SUCCEEDED(root.RecurseDeleteSubKey(sub_keys[i])));
  }

  // Now delete all the values of the root key.
  // The mi and ui values are not deleted.
  // The Last* values are not deleted.
  // TODO(Omaha): The above a temporary fix for bug 1539293. Need a better
  // long-term solution.
  size_t num_values = root.GetValueCount();
  std::vector<CString> value_names;
  for (size_t i = 0; i < num_values; ++i) {
    CString value_name;
    DWORD type = 0;
    hr = root.GetValueNameAt(i, &value_name, &type);
    ASSERT1(hr == S_OK);
    // TODO(omaha): Remove kRegValueLast* once we have an install API.
    if (SUCCEEDED(hr)) {
      if (value_name != kRegValueLastInstallerResult &&
          value_name != kRegValueLastInstallerError &&
          value_name != kRegValueLastInstallerResultUIString &&
          value_name != kRegValueLastInstallerSuccessLaunchCmdLine) {
        value_names.push_back(value_name);
      }
    }
  }

  for (size_t i = 0; i < value_names.size(); ++i) {
    VERIFY1(SUCCEEDED(root.DeleteValue(value_names[i])));
  }

  if (0 == root.GetValueCount() && 0 == root.GetSubkeyCount()) {
    VERIFY1(SUCCEEDED(RegKey::DeleteKey(root_key, false)));
  }

  return S_OK;
}

}  // namespace omaha


text:
sender: Ali Ronan
recipient: Phillis Skinner
description: suffragist, author, socialist
website: https://gm1914.wordpress.com/2016/06/09/tales-from-the-womens-peace-crusade/
born: 1876
died: 1950
received: 2017-01-07
published: 2017-02-20
draft: false
images:
  - 1.jpg
---
Dear Phillis Skinner,
You have been an inspiration to me since I read your cry for us "<u>to clamorously and unceasingly agitate</u>" for peace, for women's rights, for love.
You were so hard to find -- you ran away from London in 1912 to live with the young socialist Allen Skinner in Manchester. You left London, you got divorced, you had a child with Allen - little Jack - you went to prison for handing out anti-war leaflets in 1917. You never stopped campaigning for peace + believing there could be a better world! Thank you. As your friend Hope said: " You (were) an AMAZING woman."


text:
package com.example.tests;

public class Sample1 {

	public static void main(String[] args) {
		String line ="test1393346583,,test2047817759,!";
		System.out.println(line.split(",").length);
	}

}


text:
package com.github.thbrown.softballsim.helpers;

import static org.junit.Assert.assertThat;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import com.github.thbrown.softballsim.util.Logger;
import org.hamcrest.CoreMatchers;

public class TestUtil {

  public static ByteArrayOutputStream redirectStdOut() {
    ByteArrayOutputStream outContent = new ByteArrayOutputStream();
    System.setOut(new PrintStream(outContent));
    return outContent;
  }

  public static void asssertContainsAll(String target, String... stringsTheTargetMustContains) {
    for (String s : stringsTheTargetMustContains) {
      assertThat(target, CoreMatchers.containsString(s));
    }
  }

  /**
   * Accepts an input between floorA and ceilB and linearly maps it to a value between floorB and
   * ceilB
   */
  public static double normalize(double input, double floorA, double ceilA, double floorB, double ceilB) {
    return floorB + ((input - floorA) * (ceilB - floorB)) / (ceilA - floorA);
  };

  public static List<Long> getPredictionArray(List<Long> dataPoints) {
    if (dataPoints.size() == 0) {
      return new ArrayList<>();
    }

    List<Long> slopes = new ArrayList<>(dataPoints.size() - 1);
    for (int i = 1; i < dataPoints.size(); i++) {
      slopes.add(dataPoints.get(i) - dataPoints.get(i - 1));
    }

    List<Long> recursiveResult = getPredictionArray(slopes);
    recursiveResult.add(dataPoints.get(dataPoints.size() - 1));
    return recursiveResult;
  }
}


text:
from nova.network import model as network_model
from nova import test
from nova.tests.unit import fake_network
from nova.virt import netutils

class TestNetUtilsTestCase(test.NoDBTestCase):
    def setUp(self):
        super(TestNetUtilsTestCase, self).setUp()

    def test_get_cached_vifs_with_vlan_no_nw_info(self):
        # Make sure that an empty dictionary will be returned when
        # nw_info is None
        self.assertEqual({}, netutils.get_cached_vifs_with_vlan(None))

    def test_get_cached_vifs_with_vlan_with_no_vlan_details(self):
        network_info = fake_network.fake_get_instance_nw_info(self, 1)
        network_info[0]['vnic_type'] = network_model.VNIC_TYPE_DIRECT_PHYSICAL
        network_info[0]['address'] = "51:5a:2c:a4:5e:1b"
        self.assertEqual({}, netutils.get_cached_vifs_with_vlan(network_info))

    def test_get_cached_vifs_with_vlan(self):
        network_info = fake_network.fake_get_instance_nw_info(self, 2)
        network_info[0]['vnic_type'] = network_model.VNIC_TYPE_DIRECT_PHYSICAL
        network_info[0]['address'] = "51:5a:2c:a4:5e:1b"

        network_info[1]['vnic_type'] = network_model.VNIC_TYPE_DIRECT_PHYSICAL
        network_info[1]['address'] = "fa:16:3e:d1:28:e4"
        network_info[1]['details'] = dict(vlan='2145')
        expected = {'fa:16:3e:d1:28:e4': '2145'}
        self.assertEqual(expected,
                         netutils.get_cached_vifs_with_vlan(network_info))


text:
/*
 * 	Android API Guide
 *		http://developer.android.com/guide/topics/ui/actionbar.html
 *  Android Design Guide
 *		http://developer.android.com/design/patterns/actionbar.html
 *  Titanium Mobile will support someday
 *		https://jira.appcelerator.org/browse/TIMOB-2371
 */
var osName = Ti.Platform.osname,
	isAndroid = osName==='android',
	isIOS = osName==='iphone' || osName==='ipad' || osName==='ipod',
	theme = {
		fontFamily : isIOS ? 'Helvetica Nue' : 'Droid Sans',
		backgroundColor : '#cdcdcd',
		borderColor : '#b5b5b5',
		textColor : '#5f5f5f',
		dividerColor : '#b5b5b5',
		selectedColor : '#00b7e3',
		height : '48dp',
		buttonHeight : '46dp',
		selectedButtonHeight : '42dp',
		dividerWidth : 1,
		dividerHeight : '32dp',
		fontSize : '12dp'
	},
	events = {
		'TAB_CLICK' : 'ActionBar.NavigationTab:Click'
	};

function createNavigationTabGroup(tabs){
	var _tabs = tabs || [],
		_tabCount = _tabs.length,
		_i = 0,
		_deviceWidth = Ti.Platform.displayCaps.platformWidth,
		_width = (_deviceWidth / _tabCount) - 1,
		_selectedTab,
		_view = Ti.UI.createView({
			layout : 'horizontal',
			width : Ti.UI.FILL,
			top : 1,
			bottom : 1
		});

	for(; _i < _tabCount; _i++){
		_tabs[_i].width = _width;
		_tabs[_i] = buildTab(_tabs[_i]);
		_view.add(_tabs[_i].tabView);
		_view.add(tabSeperator());
	}

	_view.addEventListener(events.TAB_CLICK, function(e) {
		var _n = 0,
			_len = _tabs.length,
			_aTab;
		for(; _n<_len; _n++){
			_aTab = _tabs[_n];
			if(_aTab.tabView.id==_selectedTab){
				_aTab.select(false);
			}
			if(_aTab.tabView.id==e.tabId){
				_aTab.select(true);
			}
		}
		_selectedTab = e.tabId;
	});

	function tabSeperator(){
		var seperatorView = Ti.UI.createView({
				backgroundColor : theme.backgroundColor,
				width : theme.dividerWidth
			}),
			seperator = Ti.UI.createView({
				height : theme.dividerHeight,
				backgroundColor : theme.dividerColor
			});

		seperatorView.add(seperator);
		return seperatorView;
	}

	function buildTab(params){
		var _params = params || {},
			_tabView,
			_tabLabel,
			_config = {
				id : _params.id || (new Date()).getTime()+'',
				text : _params.text || "Nav",
				selectedColor : _params.selectedColor || theme.selectedColor,
				backgroundColor : _params.backgroundColor || theme.backgroundColor,
				textColor : _params.textColor || theme.textColor,
				width : _params.width || 'auto',
				selected : _params.selected || false
			};

		if(_config.selected){
			_selectedTab = _config.id;
		}

		_tabView = Ti.UI.createView({
			id : _config.id,
			backgroundColor : _config.selectedColor,
			width : _config.width,
			layout : 'vertical'
		});

		_tabLabel = Ti.UI.createLabel({
			text : _config.text,
			color  : _config.textColor,
			backgroundColor : _config.backgroundColor,
			textAlign : Ti.UI.TEXT_ALIGNMENT_CENTER,
			height : _config.selected ? theme.selectedButtonHeight : theme.buttonHeight,
			left : 0,
			right : 0,
			font   : {
				fontSize   : theme.fontSize,
				fontWeight : 'bold'
			}
		});

		_tabView.add(_tabLabel);

		_tabView.addEventListener('click', function() {
			_view.fireEvent(
				events.TAB_CLICK,
				{ tabId : _tabView.id }
			);
		});

		return {
			tabView : _tabView,
			select : function(bool){
				_tabLabel.height = bool ? theme.selectedButtonHeight : theme.buttonHeight
			}
		};
	}

	return _view;
}

function ActionBarView(args) {
	var ActionBar = Ti.UI.createView({
			height : theme.height,
			backgroundColor : theme.borderColor,
			layout : 'horizontal',
			top : 0
		}),
		navigationTabGroup = createNavigationTabGroup(args.tabs);

	ActionBar.add(navigationTabGroup);

	return ActionBar;
}

module.exports = ActionBarView;


text:
[![view on npm](http://img.shields.io/npm/v/stream-connect.svg)](https://www.npmjs.org/package/stream-connect)
[![npm module downloads](http://img.shields.io/npm/dt/stream-connect.svg)](https://www.npmjs.org/package/stream-connect)
[![Build Status](https://travis-ci.org/75lb/stream-connect.svg?branch=master)](https://travis-ci.org/75lb/stream-connect)
[![Coverage Status](https://coveralls.io/repos/75lb/stream-connect/badge.svg?branch=master&service=github)](https://coveralls.io/github/75lb/stream-connect?branch=master)
[![Dependency Status](https://david-dm.org/75lb/stream-connect.svg)](https://david-dm.org/75lb/stream-connect)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](https://github.com/feross/standard)

# stream-connect

Similar to `.pipe` except `.pipe` returns the last stream in a pipeline. stream-connect returns a stream which writes to the first stream in the pipeline and reads from the last.

## Synopsis

```js
const connect = require('stream-connect')
const fs = require('fs')

const connected = connect(stream1, stream2, stream3, stream4)

// data piped into the connected stream is transparently passed through all four internal streams
// then output into process.stdout. Errors in any of the internal streams are emitted
// by the connected stream.
process.stdin
  .pipe(connected)
  .on('error', console.error)
  .pipe(process.stdout)
```

## More detail

Consider this `.pipe` example.

```js
function getExampleStream () {
 ...
 return streamOne.pipe(streamTwo)
}
const stream = getExampleStream()
stream.on('data', function (chunk) {}) // catches data from streamOne via streamTwo
stream.on('error', function (err) {}) // catches errors only from streamTwo
stream.end('test') // is written to streamTwo
```

If you write to the output it will be written to `streamTwo`, whereas you probably wanted to write to the  start of the pipeline and read from the end. Fixed by stream-connect:

```js
const connect = require('stream-connect')
function getExampleStream () {
 ...
 return connect(streamOne, streamTwo)
}
const stream = getExampleStream()
stream.on('data', function (chunk) {}) // catches data from streamOne via streamTwo
stream.on('error', function (err) {}) // catches errors from both streamOne and streamTwo
stream.end('test') // is written to streamOne
```

Any errors emitted in `streamOne` or `streamTwo` are propagated to the output stream.

## stream-connect
**Example**
```js
const connect = require('stream-connect')
```

### connect(...streams) ⇒ [Duplex](https://nodejs.org/api/stream.html#stream_class_stream_duplex) ⏏
Connect streams.

**Kind**: Exported function

| Param | Type | Description |
| --- | --- | --- |
| ...streams | [Duplex](https://nodejs.org/api/stream.html#stream_class_stream_duplex) | One or more streams to connect. |

* * *

© 2015 Lloyd Brookes \<75pound@gmail.com\>. Documented by [jsdoc-to-markdown](https://github.com/jsdoc2md/jsdoc-to-markdown).


text:
static char secureinfo[0x111] = {0};

// Below is stolen from http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm

#define ALPHABET_LEN 256
#define NOT_FOUND patlen
#define max(a, b) ((a < b) ? b : a)

// delta1 table: delta1[c] contains the distance between the last
// character of pat and the rightmost occurence of c in pat.
// If c does not occur in pat, then delta1[c] = patlen.
// If c is at string[i] and c != pat[patlen-1], we can
// safely shift i over by delta1[c], which is the minimum distance
// needed to shift pat forward to get string[i] lined up
// with some character in pat.
// this algorithm runs in alphabet_len+patlen time.
static void make_delta1(int *delta1, u8 *pat, int patlen)
{
  int i;
  for (i=0; i < ALPHABET_LEN; i++) {
    delta1[i] = NOT_FOUND;
  }
  for (i=0; i < patlen-1; i++) {
    delta1[pat[i]] = patlen-1 - i;
  }
}

// true if the suffix of word starting from word[pos] is a prefix
// of word
static int is_prefix(u8 *word, int wordlen, int pos)
{
  int i;
  int suffixlen = wordlen - pos;
  // could also use the strncmp() library function here
  for (i = 0; i < suffixlen; i++) {
    if (word[i] != word[pos+i]) {
      return 0;
    }
  }
  return 1;
}

// length of the longest suffix of word ending on word[pos].
// suffix_length("dddbcabc", 8, 4) = 2
static int suffix_length(u8 *word, int wordlen, int pos)
{
  int i;
  // increment suffix length i to the first mismatch or beginning
  // of the word
  for (i = 0; (word[pos-i] == word[wordlen-1-i]) && (i < pos); i++);
  return i;
}

// delta2 table: given a mismatch at pat[pos], we want to align
// with the next possible full match could be based on what we
// know about pat[pos+1] to pat[patlen-1].
//
// In case 1:
// pat[pos+1] to pat[patlen-1] does not occur elsewhere in pat,
// the next plausible match starts at or after the mismatch.
// If, within the substring pat[pos+1 .. patlen-1], lies a prefix
// of pat, the next plausible match is here (if there are multiple
// prefixes in the substring, pick the longest). Otherwise, the
// next plausible match starts past the character aligned with
// pat[patlen-1].
//
// In case 2:
// pat[pos+1] to pat[patlen-1] does occur elsewhere in pat. The
// mismatch tells us that we are not looking at the end of a match.
// We may, however, be looking at the middle of a match.
//
// The first loop, which takes care of case 1, is analogous to
// the KMP table, adapted for a 'backwards' scan order with the
// additional restriction that the substrings it considers as
// potential prefixes are all suffixes. In the worst case scenario
// pat consists of the same letter repeated, so every suffix is
// a prefix. This loop alone is not sufficient, however:
// Suppose that pat is "ABYXCDEYX", and text is ".....ABYXCDEYX".
// We will match X, Y, and find B != E. There is no prefix of pat
// in the suffix "YX", so the first loop tells us to skip forward
// by 9 characters.
// Although superficially similar to the KMP table, the KMP table
// relies on information about the beginning of the partial match
// that the BM algorithm does not have.
//
// The second loop addresses case 2. Since suffix_length may not be
// unique, we want to take the minimum value, which will tell us
// how far away the closest potential match is.
static void make_delta2(int *delta2, u8 *pat, int patlen)
{
  int p;
  int last_prefix_index = patlen-1;

  // first loop
  for (p=patlen-1; p>=0; p--) {
    if (is_prefix(pat, patlen, p+1)) {
      last_prefix_index = p+1;
    }
    delta2[p] = last_prefix_index + (patlen-1 - p);
  }

  // second loop
  for (p=0; p < patlen-1; p++) {
    int slen = suffix_length(pat, patlen, p);
    if (pat[p - slen] != pat[patlen-1 - slen]) {
      delta2[patlen-1 - slen] = patlen-1 - p + slen;
    }
  }
}

static u8* boyer_moore(u8 *string, int stringlen, u8 *pat, int patlen)
{
  int i;
  int delta1[ALPHABET_LEN];
  int delta2[patlen * sizeof(int)];
  make_delta1(delta1, pat, patlen);
  make_delta2(delta2, pat, patlen);

  i = patlen-1;
  while (i < stringlen) {
    int j = patlen-1;
    while (j >= 0 && (string[i] == pat[j])) {
      --i;
      --j;
    }
    if (j < 0) {
      return (string + i+1);
    }

    i += max(delta1[string[i]], delta2[j]);
  }
  return NULL;
}

static int patch_memory(start, size, pattern, patsize, offset, replace, repsize, count)
  u8* start;
  u32 size;
  u32 patsize;
  u8 pattern[patsize];
  int offset;
  u32 repsize;
  u8 replace[repsize];
  int count;
{
  u8 *found;
  int i;
  u32 at;

  for (i = 0; i < count; i++)
  {
    found = boyer_moore(start, size, pattern, patsize);
    if (found == NULL)
    {
      break;
    }
    at = (u32)(found - start);
    memcpy(found + offset, replace, repsize);
    if (at + patsize > size)
    {
      size = 0;
    }
    else
    {
      size = size - (at + patsize);
    }
    start = found + patsize;
  }
  return i;
}

static int file_open(IFile *file, FS_ArchiveID id, const char *path, int flags)
{
  FS_Archive archive;
  FS_Path ppath;
  size_t len;

  len = strnlen(path, PATH_MAX);
  archive.id = id;
  archive.lowPath.type = PATH_EMPTY;
  archive.lowPath.size = 1;
  archive.lowPath.data = (u8 *)"";
  ppath.type = PATH_ASCII;
  ppath.data = path;
  ppath.size = len+1;
  return IFile_Open(file, archive, ppath, flags);
}

static int patch_secureinfo()
{
  IFile file;
  Result ret;
  u64 total;

  if (secureinfo[0] == 0xFF)
  {
    return 0;
  }
  ret = file_open(&file, ARCHIVE_SDMC, "/SecureInfo_A", FS_OPEN_READ);
  if (R_SUCCEEDED(ret))
  {
    ret = IFile_Read(&file, &total, secureinfo, sizeof(secureinfo));
    IFile_Close(&file);
    if (R_SUCCEEDED(ret) && total == sizeof(secureinfo))
    {
      ret = file_open(&file, ARCHIVE_NAND_RW, "/sys/SecureInfo_C", FS_OPEN_WRITE | FS_OPEN_CREATE);
      if (R_SUCCEEDED(ret))
      {
        ret = IFile_Write(&file, &total, secureinfo, sizeof(secureinfo), FS_WRITE_FLUSH);
        IFile_Close(&file);
      }
      secureinfo[0] = 0xFF; // we repurpose this byte as status
    }
  }
  else // get file from NAND
  {
    ret = file_open(&file, ARCHIVE_NAND_RW, "/sys/SecureInfo_C", FS_OPEN_READ);
    if (R_SUCCEEDED(ret))
    {
      ret = IFile_Read(&file, &total, secureinfo, sizeof(secureinfo));
      IFile_Close(&file);
      if (R_SUCCEEDED(ret) && total == sizeof(secureinfo))
      {
        secureinfo[0] = 0xFF;
      }
    }
  }
  return ret;
}

int patch_code(u64 progid, u8 *code, u32 size)
{
  if (
      progid == 0x0004003000008F02LL || // USA Menu
      progid == 0x0004003000008202LL || // JPN Menu
      progid == 0x0004003000009802LL || // EUR Menu
      progid == 0x000400300000A102LL || // CHN Menu
      progid == 0x000400300000A902LL || // KOR Menu
      progid == 0x000400300000B102LL    // TWN Menu
     )
  {
    static const char region_free_pattern[] =
    {
      0x00, 0x00, 0x55, 0xE3,
      0x01, 0x10, 0xA0, 0xE3
    };
    static const char region_free_patch[] =
    {
      0x01, 0x00, 0xA0, 0xE3,
      0x1E, 0xFF, 0x2F, 0xE1
    };
    patch_memory(code, size,
      region_free_pattern,
      sizeof(region_free_pattern), -16,
      region_free_patch,
      sizeof(region_free_patch), 1
    );
  }
  else if (progid == 0x0004013000002C02LL) // NIM
  {
    static const char block_updates_pattern[] =
    {
      0x25, 0x79, 0x0B, 0x99
    };
    static const char block_updates_patch[] =
    {
      0xE3, 0xA0
    };
    static const char block_eshop_updates_pattern[] =
    {
      0x30, 0xB5, 0xF1, 0xB0
    };
    static const char block_eshop_updates_patch[] =
    {
      0x00, 0x20, 0x08, 0x60,
      0x70, 0x47
    };
    static const char country_resp_pattern[] =
    {
      0x01, 0x20, 0x01, 0x90,
      0x22, 0x46, 0x06, 0x9B
    };
    static const char country_resp_patch_model[] =
    {
      0x06, 0x9A, 0x03, 0x20,
      0x90, 0x47, 0x55, 0x21,
      0x01, 0x70, 0x53, 0x21,
      0x41, 0x70, 0x00, 0x21,
      0x81, 0x70, 0x60, 0x61,
      0x00, 0x20
    };
    const char *country;
    char country_resp_patch[sizeof(country_resp_patch_model)];

    patch_memory(code, size,
      block_updates_pattern,
      sizeof(block_updates_pattern), 0,
      block_updates_patch,
      sizeof(block_updates_patch), 1
    );
    patch_memory(code, size,
      block_eshop_updates_pattern,
      sizeof(block_eshop_updates_pattern), 0,
      block_eshop_updates_patch,
      sizeof(block_eshop_updates_patch), 1
    );
    if (R_SUCCEEDED(patch_secureinfo()))
    {
      switch (secureinfo[0x100])
      {
        case 1: country = "US"; break;
        case 2: country = "GB"; break; // sorry rest-of-Europe, you have to change this
        case 3: country = "AU"; break;
        case 4: country = "CN"; break;
        case 5: country = "KR"; break;
        case 6: country = "TW"; break;
        default: case 0: country = "JP"; break;
      }
      // patch XML response Country
      memcpy(country_resp_patch,
        country_resp_patch_model,
        sizeof(country_resp_patch_model)
      );
      country_resp_patch[6] = country[0];
      country_resp_patch[10] = country[1];
      patch_memory(code, size,
        country_resp_pattern,
        sizeof(country_resp_pattern), 0,
        country_resp_patch,
        sizeof(country_resp_patch), 1
      );
    }
  }
  else if (progid == 0x0004013000008002LL) // NS
  {
    static const char stop_updates_pattern[] =
    {
      0x0C, 0x18, 0xE1, 0xD8
    };
    static const char stop_updates_patch[] =
    {
      0x0B, 0x18, 0x21, 0xC8
    };
    patch_memory(code, size,
      stop_updates_pattern,
      sizeof(stop_updates_pattern), 0,
      stop_updates_patch,
      sizeof(stop_updates_patch), 2
    );
  }
  else if (progid == 0x0004013000001702LL) // CFG
  {
    static const char secureinfo_sig_check_pattern[] =
    {
      0x06, 0x46, 0x10, 0x48, 0xFC
    };
    static const char secureinfo_sig_check_patch[] =
    {
      0x00, 0x26
    };
    static const char secureinfo_filename_pattern[] =
    {
      0x53, 0x00, 0x65, 0x00,
      0x63, 0x00, 0x75, 0x00,
      0x72, 0x00, 0x65, 0x00,
      0x49, 0x00, 0x6E, 0x00,
      0x66, 0x00, 0x6F, 0x00,
      0x5F, 0x00
    };
    static const char secureinfo_filename_patch[] =
    {
      0x43, 0x00
    };
    // disable SecureInfo signature check
    patch_memory(code, size,
      secureinfo_sig_check_pattern,
      sizeof(secureinfo_sig_check_pattern), 0,
      secureinfo_sig_check_patch,
      sizeof(secureinfo_sig_check_patch), 1
    );
    if (R_SUCCEEDED(patch_secureinfo()))
    {
      // use SecureInfo_C
      patch_memory(code, size,
        secureinfo_filename_pattern,
        sizeof(secureinfo_filename_pattern), 22,
        secureinfo_filename_patch,
        sizeof(secureinfo_filename_patch), 2
      );
    }
  }
  return 0;
}