+WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx,
+ const struct auth_session_info *session_info,
+ struct messaging_context *msg_ctx,
+ const char *printer, struct GUID *guid)
+{
+ TALLOC_CTX *tmp_ctx;
+ enum winreg_Type type;
+ DATA_BLOB blob;
+ uint32_t len;
+ NTSTATUS status;
+ WERROR result;
+
+ tmp_ctx = talloc_new(mem_ctx);
+ if (tmp_ctx == NULL) {
+ DEBUG(0, ("out of memory?!\n"));
+ return WERR_NOMEM;
+ }
+
+ result = winreg_get_printer_dataex_internal(tmp_ctx, session_info,
+ msg_ctx, printer,
+ SPOOL_DSSPOOLER_KEY,
+ "objectGUID",
+ &type,
+ &blob.data,
+ &len);
+ if (!W_ERROR_IS_OK(result)) {
+ DEBUG(0, ("Failed to get GUID for printer %s\n", printer));
+ goto out_ctx_free;
+ }
+ blob.length = (size_t)len;
+
+ /* We used to store the guid as REG_BINARY, then swapped
+ to REG_SZ for Vista compatibility so check for both */
+
+ switch (type) {
+ case REG_SZ: {
+ bool ok;
+ const char *guid_str;
+ ok = pull_reg_sz(tmp_ctx, &blob, &guid_str);
+ if (!ok) {
+ DEBUG(0, ("Failed to unmarshall GUID for printer %s\n",
+ printer));
+ result = WERR_REG_CORRUPT;
+ goto out_ctx_free;
+ }
+ status = GUID_from_string(guid_str, guid);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("bad GUID for printer %s\n", printer));
+ result = ntstatus_to_werror(status);
+ goto out_ctx_free;
+ }
+ break;
+ }
+ case REG_BINARY:
+ if (blob.length != sizeof(struct GUID)) {
+ DEBUG(0, ("bad GUID for printer %s\n", printer));
+ result = WERR_REG_CORRUPT;
+ goto out_ctx_free;
+ }
+ memcpy(guid, blob.data, sizeof(struct GUID));
+ break;
+ default:
+ DEBUG(0,("GUID value stored as invalid type (%d)\n", type));
+ result = WERR_REG_CORRUPT;
+ goto out_ctx_free;
+ break;
+ }
+ result = WERR_OK;
+
+out_ctx_free:
+ talloc_free(tmp_ctx);
+ return result;
+}
+