<workbookProtection>
(Workbook Protection)
This element specifies options for protecting data in the workbook. Applications may use workbook protection to prevent anyone from accidentally changing, moving, or deleting important data. This protection may be ignored by applications which choose not to support this optional protection mechanism.
Parent Elements |
---|
|
Attributes |
Description |
||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Specifies a boolean value that indicates whether the workbook is locked for revisions. The possible values for this attribute are defined by the XML Schema boolean datatype. |
||||||||||||||||||||||||||||||||||||||||||
|
Specifies a boolean value that indicates whether structure of workbook is locked. A value of on, 1, or true indicates the structure of the workbook is locked. Worksheets in the workbook can't be moved, deleted, hidden, unhidden, or renamed, and new worksheets can't be inserted. A value of off, 0, or false indicates the structure of the workbook is not locked. The default value for this attribute is false. The possible values for this attribute are defined by the XML Schema boolean datatype. |
||||||||||||||||||||||||||||||||||||||||||
|
Specifies a boolean value that indicates whether the windows that comprise the workbook are locked. A value of on, 1, or true indicates the workbook windows are locked. Windows are the same size and position each time the workbook is opened. A value of off, 0, or false indicates the workbook windows are not locked. The default value for this attribute is false. The possible values for this attribute are defined by the XML Schema boolean datatype. |
||||||||||||||||||||||||||||||||||||||||||
|
Specifies the hash of the password required for unlocking revisions in this workbook. The hash is generated from an 8-bit wide character. 16-bit Unicode characters must be converted down to 8 bits before the hash is computed, using the following logic: For SpreadsheetML password hash purposes, Unicode UTF-16 input code points are converted to an “ansi” single or double byte code page from the following list:
Code points with no representation in the target code page are replaced with Unicode character 0x3f (?). The necessary mapping tables can be found at the following location: http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/ . Code pages 932, 936, 949, and 950 are “Double Byte” code pages. The remainder of the “ANSI” code pages supported by windows are “Single Byte” code pages. For single byte code pages each Unicode code point is replaced by a single byte or 0x3f if an appropriate character doesn’t exist in the code page. For double byte code pages, each Unicode code point is replaced by either a single byte, or a two byte sequence, depending on the input character, or 0x3f if an appropriate character doesn’t exist in the code page. In our tables the target is a single byte sequence if the most significant byte is 0x00, otherwise it is a double byte sequence, with the lead byte being the most significant byte. To convert, first check if conversion is being done to a single or double byte code page and load the appropriate WCTABLE code page table. For each input WCHAR, look up the code point in the WCTABLE. There are 3 possibilities: Not found, single byte, or double byte. If the input WCHAR is not found, append 0x3f and continue to the next WCHAR. If the result is a single byte, check to make sure the entry in the MBTABLE matches the input. If it matches, append the single byte to the output. If it does not match, append 0x3f to the output. If the result is a double byte,check to make sure the entry in the DBCSENTRY table for the appropriate lead byte matches the input WCHAR. If it matches, append the lead byte and trail byte to the output. If it does not match, append 0x3f to the output. The following pueudocode describes how this conversion should be done: int WideCharToMultiByte(WCHAR* wszInput, byte* szOutput) { // Remember output start so we can return length byte* szOutputStart = szOutput; // Ask the system for the current ANSI code page, which // on windows is a system setting. int iCodePage = GetCurrentAnsiCodePage(); // Load Code Page Tables // This will depend on how the code pages are represented on // the target machine. TABLECLASS represents some abstract // representation of this structure here. TABLECLASS pTables = LoadCodePageTables(iCodePage); bool bDoubleByte = false; if (iCodePage == 932 || iCodePage == 936 || iCodePage == 949 || iCodePage == 950) bDoubleByte = true; while (*wszInput != 0) { if (bDoubleByte) szOutput = AppendDoubleByte(pTables, *wszInput, szOutput); else szOutput = AppendSingleByte(pTables, *wszInput, szOutput); // Read next input WCHAR wszInput++; } // Null terminate the output *szOutput = 0; // Return output length return szOutput – szOutputStart; } byte* AppendSingleByte(TABLECLASS pTables, WCHAR wcIn, byte* szOutput) { // Look up byte that we want to append. byte bOut = pTables->LookUpSingleByte(wcIn); // Make sure that bOut matches the input, otherwise use ? // (ie: no best fit behavior allowed) if (wcIn != pTables->LookUpWideChar(bOut)) bOut = 0x3f; *szOutput = bOut; szOutput++; return szOutput; } byte* AppendDoubleByte(TABLECLASS pTables, WCHAR wcIn, byte* szOutput) { // Look up bytes that we want to append. UINT16 bytesOut = pTables->LookUpDoubleByte(wcIn); // See if it is a single or double byte sequence if (bytesOut & 0xFF00) { // It is a double byte sequence // Make sure that bytesOut matches the input, otherwise use ? // (ie: no best fit behavior allowed) if (wcIn != pTables->LookUpWideChar(bytesOut)) { // Use ?, it will be added below bytesOut = 0x003f; } else { // It matched, use the lead byte we found // trail byte will be added below *szOutput = bytesOut >> 8; szOutput++; } else { // It is a single byte sequence // Make sure that bytesOut matches the input, otherwise use ? // (ie: no best fit behavior allowed) if (wcIn != pTables->LookUpWideChar(bytesOut & 0xFF)) bytesOut = 0x003f; } // Add the single or trail byte *szOutput = bytesOut & 0xFF; szOutput++; return szOutput; } class pTables { // Construction depends on how you choose to store & load the // table files byte LookUpSingleByte(WCHAR wcIn) { // How you access the table depends on your storage mechanism. // Look up the line in WCTABLE where the first column matches wcIn, // and then return the byte value from the second column. if (exists WCTABLE{wcIn}) return WCTABLE{wcIn}.SecondColumn; // If it doesn’t exist, return ? return 0x3f; } UINT16 LookUpDoubleByte(WCHAR wcIn) { // How you access the table depends on your storage mechanism. // Look up the line in WCTABLE where the first column matches wcIn, // and then return the double byte value from the second column. if (exists WCTABLE{wcIn}) return WCTABLE{wcIn}.SecondColumn; // If it doesn’t exist, return ? return 0x003f; } // Overload that looks up wide chars from single byte code points. WCHAR LookUpWideChar(byte bIn) { // How you access the table depends on your storage mechanism. // Look up the line in MBTABLE where the first column matches bIn, // and then return the WCHAR value from the second column. if (exists MBTABLE{bIn}) return MBTABLE{bIn}.SecondColumn; // If it doesn’t exist, return ? return 0x003f; } // Overload that looks up wide chars from double byte code points WCHAR LookUpWideChar(UINT16 bytesIn) { // How you access the table depends on your storage mechanism. // First find the DBCSTABLE where the LeadByte matches // the lead (most significant) input byte. if (exists DBCSTABLE{bytesIn >> 8)) { DbcsTable = DBCSTABLE{bytesIn >> 8); // Look up the line in DbcsTable where the first column // matches the input trail (least significant) byte, // and then return the WCHAR value from the second column. if (exists DbcsTable{bytesIn & 0xFF}) return DbcsTable{bytesIn & 0xFF}.SecondColumn; } // Either the lead byte table or specific trail byte // doesn’t exist in the table, return ? return 0x003f; } } The resulting value is hashed using the algorithm defined below. // Function Input: // szPassword: NULL terminated C-Style string // cchPassword: The number of characters in szPassword (not including the NULL terminator) WORD GetPasswordHash(const CHAR *szPassword, int cchPassword) { WORD wPasswordHash; const CHAR *pch; wPasswordHash = 0; if (cchPassword > 0) { pch = &szPassword[cchPassword]; while (pch-- != szPassword) { wPasswordHash = ((wPasswordHash >> 14) & 0x01) | ((wPasswordHash << 1) & 0x7fff); wPasswordHash ^= *pch; } wPasswordHash ^= (0x8000 | ('N' << 8) | 'K'); } return(wPasswordHash); } The possible values for this attribute are defined by the ST_UnsignedShortHex simple type (§3.18.87). |
||||||||||||||||||||||||||||||||||||||||||
|
Specifies the hash of the password required for unlocking revisions in this workbook. The hash is generated from an 8-bit wide character. 16-bit Unicode characters must be converted down to 8 bits before the hash is computed, using the following logic: For SpreadsheetML password hash purposes, Unicode UTF-16 input code points are converted to an “ansi” single or double byte code page using the logic defined in the preceding The resulting value is hashed using the algorithm defined below. // Function Input: // szPassword: NULL terminated C-Style string // cchPassword: The number of characters in szPassword (not including the NULL terminator) WORD GetPasswordHash(const CHAR *szPassword, int cchPassword) { WORD wPasswordHash; const CHAR *pch; wPasswordHash = 0; if (cchPassword > 0) { pch = &szPassword[cchPassword]; while (pch-- != szPassword) { wPasswordHash = ((wPasswordHash >> 14) & 0x01) | ((wPasswordHash << 1) & 0x7fff); wPasswordHash ^= *pch; } wPasswordHash ^= (0x8000 | ('N' << 8) | 'K'); } return(wPasswordHash); } The possible values for this attribute are defined by the ST_UnsignedShortHex simple type (§3.18.87). |
The following XML Schema fragment defines the contents of this element:
<complexType name="CT_WorkbookProtection">
<attribute name="workbookPassword" type="ST_UnsignedShortHex" use="optional"/>
<attribute name="revisionsPassword" type="ST_UnsignedShortHex" use="optional"/>
<attribute name="lockStructure" type="xsd:boolean" use="optional" default="false"/>
<attribute name="lockWindows" type="xsd:boolean" use="optional" default="false"/>
<attribute name="lockRevision" type="xsd:boolean" use="optional" default="false"/>
</complexType>